Par rapport à la classe Model
standard, la classe PolyModel
offre davantage de flexibilité dans la définition de modèles, permettant ainsi à une application d'accepter les requêtes polymorphes.
Une requête générée à partir d'une classe dérivée de PolyModel
peut renvoyer des résultats constitués d'instances de la classe ou de l'une ou l'autre de ses sous-classes.
Ce type de requête est défini dans google.appengine.ext.ndb.polymodel
. L'exemple ci-dessous illustre la flexibilité offerte par la classe PolyModel :
from google.appengine.ext import ndb from google.appengine.ext.ndb import polymodel class Contact(polymodel.PolyModel): phone_number = ndb.PhoneNumberProperty() address = ndb.PostalAddressProperty() class Person(Contact): first_name = ndb.StringProperty() last_name = ndb.StringProperty() mobile_number = ndb.PhoneNumberProperty() class Company(Contact): name = ndb.StringProperty() fax_number = ndb.PhoneNumberProperty() p = Person(phone_number='1-206-555-9234', address='123 First Ave., Seattle, WA, 98101', first_name='Alfred', last_name='Smith', mobile_number='1-206-555-0117') p.put() c = Company(phone_number='1-503-555-9123', address='P.O. Box 98765, Salem, OR, 97301', name='Data Solutions, LLC', fax_number='1-503-555-6622') c.put() for contact in Contact.query(): print 'Phone: %s\nAddress: %s\n\n' % (contact.phone_number, contact.address)
La requête Contact.query()
renvoie des instances de Person
et de Company
. Si Contact
était dérivé de Model
au lieu de PolyModel
, chaque classe aurait une valeur kind
différente et la requête Contact.query()
ne renverrait pas d'instances des sous-classes de Contact
.
Si vous souhaitez ne récupérer que les instances de Person
, utilisez Person.query()
. Vous pouvez également utiliser Contact.query(Contact.class_ == 'Person')
.
En plus des méthodes Model habituelles, la méthode PolyModel propose certaines alternatives intéressantes :
_get_kind()
: nom de la classe racine, par exemplePerson._get_kind() == 'Contact'
. La classe racine, "Contact" dans cet exemple, peut remplacer cette méthode de façon à utiliser un autre nom en tant que type ("kind") utilisé dans le datastore (pour toute la hiérarchie racine associée)._class_name()
: nom de la classe actuelle, par exemplePerson._class_name() == 'Person'
. Une classe feuille, "Person" dans notre exemple, peut remplacer cette méthode pour utiliser un autre nom en tant que nom de classe et dans la clé de la classe. Une classe non-feuille peut aussi remplacer cette méthode, mais attention : ses sous-classes doivent également la remplacer, sinon elles utiliseront toutes le même nom de classe et vous serez vite perdu._class_key()
: liste de noms de classes indiquant la hiérarchie. Exemple :Person._class_key() == ['Contact', 'Person']
. Pour les hiérarchies plus profondes, cela inclut toutes les bases entrePolyModel
et la classe actuelle, y compris cette dernière, à l'exclusion du PolyModel lui-même. Identique à la valeur de la propriétéclass_
. Son nom dans le datastore est "class".
Étant donné que le nom de la classe est utilisé dans la propriété class_
et que cette dernière est utilisée pour distinguer les sous-classes, les noms de classes (tels que renvoyés par _class_name()
) doivent être uniques parmi ces sous-classes.