La classe PolyModel
consente a un'applicazione di definire modelli che supportano query polimorfiche in modo più flessibile rispetto alla classe Model
standard.
Una query prodotta da una classe derivata PolyModel
può avere risultati che sono istanze della classe o di uno dei suoi sottoclassi.
È definito in google.appengine.ext.ndb.polymodel
. L'esempio seguente mostra la flessibilità offerta dalla 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)
Contact.query()
restituisce istanze di Person
e Company
;
se Contact
deriva da Model
anziché da
PolyModel
, ogni classe avrebbe un kind
diverso
e Contact.query()
non restituirebbe istanze di
sottoclassi appropriate di Contact
.
Se vuoi recuperare solo le istanze Person
,
utilizza Person.query()
. Puoi anche utilizzare
Contact.query(Contact.class_ == 'Person')
.
Oltre ai metodi Model standard, PolyModel ha alcuni metodi di classe interessanti:
_get_kind()
: il nome della classe principale; ad es.Person._get_kind() == 'Contact'
. La classe principale, Contact in questo esempio, può eseguire l'override di questo metodo per utilizzare un nome diverso rispetto al tipo utilizzato nel datastore (per l'intera gerarchia con radice qui)._class_name()
: il nome della classe corrente; ad es.Person._class_name() == 'Person'
. Una classe di primo livello, Person nel nostro esempio, può eseguire l'override di questo metodo per utilizzare un nome diverso come nome della classe e nella chiave della classe. Anche una classe non foglia può eseguire l'override di questo metodo, ma attenzione: anche i suoi sottoclassi devono eseguirlo, altrimenti utilizzeranno tutti lo stesso nome di classe e presto avrai molta confusione._class_key()
: un elenco di nomi di classi che indica la gerarchia. Ad esempio,Person._class_key() == ['Contact', 'Person']
. Per gerarchie più profonde, verranno incluse tutte le basi traPolyModel
e la classe corrente, inclusa quest'ultima, ma escluso il PolyModel stesso. È lo stesso del valore della proprietàclass_
. Il nome del datastore è "class".
Poiché il nome della classe viene utilizzato nella proprietà class_
e questa proprietà viene utilizzata per distinguere tra le sottoclassi,
i nomi delle classi (come restituiti da _class_name()
) devono essere univoci
tra queste sottoclassi.