Henri
Thanks will try.
stsouko
def __init__(self, title):
slug = xxx(title)
super().__init__(title=title, slug=slug)
Henri
Hmm now I have
class Article(db.Entity):
_table_ = 'articles'
slug = Required(str, 200, unique=True)
title = Required(str, 255)
description = Required(LongStr)
body = Required(LongStr)
created_at = Required(datetime, 0, default=datetime.utcnow)
updated_at = Required(datetime, 0, default=datetime.utcnow)
author = Required(User, reverse="articles")
favorited = Set(User, reverse="favorites")
comments = Set("Comment")
tag_list = Set("Tag")
def _unique_check(self, text, uids):
if text in uids:
return False
return not self.exists(slug=text)
def _slugify_url_unique(self, text):
slugify_url_unique = UniqueSlugify(
unique_check=self._unique_check, uids=['feed']
)
slugify_url_unique.to_lower = True
slugify_url_unique.stop_words = ('a', 'an', 'the')
slugify_url_unique.max_length = 200
return slugify_url_unique(text)
def __init__(
self, title, description, body, author, tag_list
):
slug = self._slugify_url_unique(title)
super().__init__(
slug=slug, title=title, description=description,
body=body, author=author, tag_list=tag_list
)But getting AttributeError: 'Article' object has no attribute 'exists'. Shouldn't it have that attribute?
Alexander
No, this method is defined for entity class only. You can write self.__class__.exists(...) instead.
Maybe in the future we'll make it a usual classmethod which can be called both from class and from object
Henri
@akozlovsky Why does
def before_insert(self):
self.slug = self._slugify_url_unique(self.title)doesn't work?
Alexander
What exception did you get?
Henri
ValueError: Attribute Article.slug is required
Alexander
before_insert works before the INSERT command is sent to the database, not before the __init__ code is executed.
When the attribute is specified as required, Pony does not allow to create an instance of object without that attribute defined. We can add something like option delayed_check=True to allow temporary creation of object without all required attributes, but I'm not sure this is a good practice.
I think you can create make_article function (or Article.make classmethod) which will create a slug before creating an Article instance:
class Article(db.Entity):
...
@classmethod
def make(cls, **kwargs):
if `slug` not in kwargs:
kwargs['slug'] = cls._slugify_url_unique(kwargs['title'])
return cls(**kwargs)
With this approach, you need to make _slugify_url_unique and _unique_check classmethods too
Henri
And would it be possible to set a function as default value?
Alexander
Sure, you can do something like:
from datetime import datetime
from uuid import UUID, uuid4
class MyObject(db.Entity):
created_at = Required(datetime, default=datetime.now)
guid = Required(UUID, unique=True, default=uuid4)
Henri
But not with an argument, right?
Alexander
Sure. With argument it will be just one specific value
Henri
Matthew
I either just use Optional, or set a fake initial value to be overwritten in after_insert
Henri
Yeah thought about that. A reason why you use after_insert not before_insert?
Matthew
oh that was just an example :) depends on the usecase
Henri
As slug is unique I think I cannot use Optional. Maybe use UUID as default.
Matthew
that would work
Alexander
Just for case it is possible for unique attribute to be Optional, because in all databases except MS SQL Server NULL values are not considered to be unique
Alexander
So it is possible to have multiple NULL values in unique column
Henri
Oh so I could set default to null and make it Optional.
Alexander
yes
Henri
So this sounds actually the least 'hacky'. 😉
Henri
@akozlovsky Getting
TypeError: Default value for non-nullable attribute Article.slug cannot be set to Nonewhen setting
class Article(db.Entity):
_table_ = 'articles'
slug = Optional(str, 200, unique=True, default=None)
title = Required(str, 255)From the documentaion unique optional fields should be nullable:
> If an optional string attribute is used as a unique key or as a part of a unique composite key, it will always have nullable set to True automatically.
Henri
I'm getting also
pony.orm.core.TransactionIntegrityError: Object Article[new:1] cannot be stored in the database. IntegrityError: NOT NULL constraint failed: articles.slugfor SQLITE when not using before_insert.
When adding nullable=True and using
def before_insert(self):
if not self.slug:
self.slug = self._slugify_url_unique(self.title)everything works fine! 😃
Lucky
^^'
Juan Antonio
Which is the proper way to separate the models into different files? I have users.py with the following content:
from pony.orm import *
from datetime import datetime
db = Database()
class User(db.Entity):
uuid = PrimaryKey(int, auto=True)
name = Required(str)
token = Required(str)
registered_at = Required(datetime)
active = Required(bool)
And the main.py with this:
from pony.orm import *
from models.users import User
def main():
db = Database()
db.bind(provider='mysql', host='127.0.0.1', port=3306,
user='root', passwd='example', db='example')
sql_debug(True)
db.generate_mapping(create_tables=True)
if __name__ == '__main__':
main()
But when I execute the main function it does not create the tables and it does not throw any exception. The code works if I put it into the same file.
Henri
You have to import db from users. Not create it a second time.
Juan Antonio
Will try tomorrow morning and see if it works. Thank you :D
Nickolai
hi all! Is pony has a on_save or before_save methods for calling on pony entities creation? i want to do some actions before pony save data
Alexey
hi Nickolai
https://docs.ponyorm.com/api_reference.html#entity-hooks
Anonymous
Hey
- At work were having a discussion about whether to bind and execute pony calls in functional manner, or, whether to keep the bindings and store them in a dictionary. We're connecting to multiple databases as multiple users, so the diversity cannot be avoided.
Any thoughts on performance here?
A) Use and drop the bindings - the users wont notice.
B) Keep and maintain the bindings? it matters.
Matthew
Is it in a long running process?
Anonymous
Could be.
Anonymous
Let's say yes.
Matthew
How many connections?
Anonymous
<100
Matthew
are all connections used roughly equally?
Anonymous
Yes. They're balanced.
Matthew
So it seems like no individual connection will ever go a long time without being used?
Anonymous
The user-session lifetime is on average 120 minutes.
Anonymous
So I was thinking of purging them after that.
Matthew
Unless the databases suffer a shortage of connections, I think keeping around all connections is reasonable
Matthew
connections are cheap for both the database and python
Anonymous
It's all postgres, so I doubt the database will suffer :-)
Matthew
Agreed
Anonymous
Thank M.👍
Matthew
does the postgres driver have automatic timeouts with automatic reconnects?
Anonymous
I wouldn't know. I've just dictated to the devs to use pony.
Anonymous
I believe pony uses psycopg behind the scenes.
Matthew
Yep, psycopg2
Matthew
I think it'll be fine
Anonymous
We haven't constrained the timeout settings.
Anonymous
Final question: If the binding is lost either side, do you know if pony tries to rebind/reconnect?
Matthew
I don't know I'm afraid, you could probably test it by killing postgres, waiting a few minutes then launching postgres again, then try to run a query
Anonymous
"testing determines all truth".
I'll do that.
Alexander
Hi Bjorn! On db.bind(...) Pony opens connection to the database and then store it in a thread-local connection pool.
When application code enters db_session and makes a query, Pony takes already opened connection from the pool and use it. After exiting db_session, connection is returned to the pool. If you enable logging, you will see RELEASE CONNECTION message from Pony. It means that the connection is not closed, but was returned to the connection pool.
Sometimes connection is closed by database server, for example when database server was restarted. After that a previously opened connection becomes invalid. If such disconnect happens, most probably it was between db_sessions, but sometimes it may happens right during active db_session. Pony is prepared to such situations, and may reconnect to the database in an intelligent matter.
If Pony executes a query and receive an error that connection is closed, it check the state of db_session in order to know was any updates already sent to the database during current db_session. If db_session just started, or all queries were just SELECTs, Pony assumes it is safe to re-open connection under the hood and continue the same db_session as if nothing unusual is happened. But if some updates were already sent to the database during active db_session before the previous connection becomes invalid, it means these updates are lost, and it is impossible to continue this db_session. Then Pony throws an exception.
But in most cases Pony is able to reconnect silently so application code don't notice anything.
If you want to close connection which is stored in the connection pool, you can perform db.disconnect() call. In multi-threaded application this needs to be done in each thread separately
Anonymous
Wow. Thanks. Let me read it twice. ...
Anonymous
Wow x 2. I think we should add this to the docs in https://docs.ponyorm.com/transactions.html#working-with-db-session
Anonymous
under "handling disruptions"
Nickolai
By default pony create db tables with latin1_swedish_ci encoding. I using db.generate_mapping(create_tables=True) snippet. But it this case i cant save unicode strings(python3 strings) for entity type str. What i should to do to resolve this problem?
Alexander
Alexander
Alexander
I think Pony does not specify encoding when creating a table, and use default encoding for the database. When you create a new database, please set UTF8 encoding as default
Nickolai
Alexander
Pony cannot create a database. Creating database requires admin privileges, and Pony typically connects as a restricted user. It may be dangerous to connect to database from application code using admin privileges.
Regarding encoding, previously Pony supported working with custom encoding, but now it assumes the encoding is UTF8. Maybe we can reconsider this
Matthew
If I create a composite_key(a, b) with postgres, does that imply that an index has also been created on a and b?
Matthew
ah it seems that postgres creates an index as part of creating the constraint
Matthew
it was not helping a simple query at all, but an additional index on a made the query fast
Matthew
my above messages are an example of the risks of doing database performance analysis after only half a cup of coffee.
Alexander
Hi guys, we released Pony 0.7.3. You can see description here: https://blog.ponyorm.com/2017/10/23/pony-orm-release-0-7-3/
initial
Trying to create some object that have relationships but running into an Attribute is required error
Alexander
If an attribute is required, you need to assign it durng object initialization. In order to do this, you need to create an object on the other side of relationship earlier, and specify it in constructor arguments of you second object
Lucky
initial
Henri
Henri
# After the 0.8 release
q5 = q.order_by(lambda o: o.customer.name)
Henri
@luckydonald So it will be similar to the new where method.
Henri
@akozlovsky The @db_session 'ddl' parameter seems not be documented.