The PolyModel
class lets an application define models
that can be superclasses for other data model
definitions. A query produced from a PolyModel
class
can have results that are instances of the class or any of its subclasses.
It is defined in google.appengine.ext.ndb.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()
returns Person
and Company
instances;
if Contact
derived from Model
instead of from
PolyModel
, each class would have a different kind
and Contact.query()
would not return instances of
proper subclasses of Contact
.
If you wish to retrieve only Person
instances,
use Person.query()
. You could also use
Contact.query(Contact.class_ == 'Person')
.
In addition to the regular Model methods, PolyModel has some interesting class methods:
_get_kind()
: the name of the root class; e.g.Person._get_kind() == 'Contact'
. The root class, Contact in this example, may override this method to use a different name as the kind used in the datastore (for the entire hierarchy rooted here)._class_name()
: the name of the current class; e.g.Person._class_name() == 'Person'
. A leaf class, Person in our example, may override this method to use a different name as the class name and in the class key. A non-leaf class may also override this method, but beware: its subclasses should also override it, or else they will all use the same class name, and you will soon be very confused._class_key()
: a list of class names giving the hierarchy. For example,Person._class_key() == ['Contact', 'Person']
. For deeper hierarchies, this will include all bases betweenPolyModel
and the current class, including the latter, but excluding PolyModel itself. This is the same as the value of theclass_
property. Its datastore name is 'class'.
Since the class name is used in the class_
property
and this property is used to distinguish between the subclasses,
the class names (as returned by _class_name()
) should be unique
among those subclasses.