PolyModel 类

与标准 Model 类相比,PolyModel 类让应用能够以更灵活的方式定义支持多态查询的模型。由 PolyModel 派生类生成的查询的结果可以是该类或其任意子类的实例

该类在 google.appengine.ext.ndb.polymodel 中定义。以下示例展示了 PolyMode 类提供的灵活性。

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() 返回 PersonCompany 实例;如果 Contact 是从 Model 中派生的(而非从 PolyModel 中),则每个类的 kind 将各不相同,且 Contact.query() 不会返回 Contact 适当子类的实例。

如果您只想检索 Person 实例,请使用 Person.query()。此外,您也可以使用 Contact.query(Contact.class_ == 'Person')

除了常规的 Model 方法,PolyModel 还有一些有趣的类方法:

  • _get_kind():根类名称;例如 Person._get_kind() == 'Contact'。根类(本示例中的 Contact)可以替换此方法,使用不同的名称作为数据存储区中使用的种类(应用于此处的整个根层次结构)。
  • _class_name():当前类名称;例如 Person._class_name() == 'Person'。叶类(本示例中的 Person)可以替换此方法,使用不同的名称作为类名和类键。非叶类也可以替换此方法,但要注意:非叶类的子类也应替换此方法,否则它们都将使用相同的类名,很快就会让你困惑不已。
  • _class_key():提供层次结构的类名列表。例如,Person._class_key() == ['Contact', 'Person']。对于更深的层次结构,这将包括 PolyModel 和当前类之间的所有基类,其中包含当前类,但不包含 PolyModel 本身。此值与 class_ 属性的值相同。其数据存储区名称为“class”。

由于该类名用于 class_ 属性中,而此属性用于区分子类,因此由 _class_name() 返回的类名在子类中应是唯一的。