Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discriminate Pony-generated fields in entities (implicit primary key) #77

Closed
crazygolem opened this issue Sep 25, 2014 · 1 comment
Closed

Comments

@crazygolem
Copy link

When Pony generates for an Entity a field that has not been specified by the user in the class definition (I know of this behavior only for Entity subclasses that do not specify a PrimaryKey field), there is currently no straightforward way to now whether that field was specified by the user or generated by Pony.

Would it be possible to have an is_implicit (or any better name) field in Attribute that is False except when the field was generated by Pony, like in the case of an implicit primary key?

@kozlovsky
Copy link
Member

Thanks for the suggestion, added to PonyORM 0.6

I know of this behavior only for Entity subclasses that do not specify a PrimaryKey field

The value of is_implicit field of primary key attribute has no relation to subclasses. Even for single class its primary key can be implicit:

>>> from pony.orm import *
>>> db = Database('sqlite', ':memory:')
>>> class Person(db.Entity):
...     name = Required(str)
...     
>>> Person._attrs_
[Person.id, Person.name]
>>> Person.id.is_implicit
True
>>> Person.name.is_implicit
False

In case of inheritance, it is discriminator attribute which can be implicit. Pony uses the value of discriminator attribute in order to determine a Python class which correspond to the specific database row:

>>> db = Database('sqlite', ':memory:')
>>> class Person(db.Entity):
...     name = Required(str)
... 
>>> class Student(Person):
...     gpa = Required(float)
...     
>>> Person._attrs_
[Person.id, Person.name, Person.classtype]
>>> Student._attrs_
[Person.id, Person.name, Person.classtype, Student.gpa]
>>> Person._discriminator_attr_
Person.classtype
>>> Person._discriminator_
'Person'
>>> Student._discriminator_
'Student'
>>> Person._discriminator_attr_.is_implicit
True
>>> Person._discriminator_attr_.py_type
<type 'str'>
>>> db.generate_mapping(create_tables=True)
>>> p1 = Person(name='John')
>>> s1 = Student(name='Mike', gpa=4.5)
>>> p1.classtype
'Person'
>>> s1.classtype
'Student'

It is possible to specify custom discriminator attribute which type is not str:

>>> class Person(db.Entity):
...     _discriminator_ = 1
...     kind = Discriminator(int)
...     name = Required(str)
... 
>>> class Student(Person):
...     _discriminator_ = 2
...     gpa = Required(float)
... 
>>> db.generate_mapping(create_tables=True)
>>> p1 = Person(name='John')
>>> s1 = Student(name='Mike', gpa=4.5)
>>> Person._discriminator_attr_
Person.kind
>>> Person._discriminator_attr_.is_implicit
False
>>> p1.kind
1
>>> p1._discriminator_attr_
1
>>> s1._discriminator_attr_
2

You may wonder why the value of p1._discriminator_attr_ is 1 here and not Person.kind. This is because in Pony each attribute is a descriptor, and when descriptor accessed from the object instance, the value of descriptor.__get__(obj) is returned and not the descriptor itself. In order to retrieve discriminator attribute of specific entity instance in a generic way, you can write obj.__class__._discriminator_attr_.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants