与标准 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()
返回 Person
和 Company
实例;如果 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()
返回的类名在子类中应是唯一的。