The PolyModel
class lets an application define models that
support polymorphic queries, in a more flexible way than the standard Model
class.
A query produced from a PolyModel
derived class can have results that are instances
of the class or
any of its subclasses.
It is defined in google.appengine.ext.ndb.polymodel
. The following example shows
the flexibility provided by the PolyModel class.
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 \n Address: %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 betweenPolyModeland 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.

