PolyModel 类是用于数据模型定义的超类,这些数据模型定义本身也可以是其他数据模型定义的超类。从 PolyModel 类生成的查询的结果可以是该类或其任意子类的实例。
PolyModel 由 google.appengine.ext.db.polymodel 模块提供。
PolyModel 是 Model 的子类,并从该类继承了它的类方法及实例方法。PolyModel 类覆盖了多个 Model 方法,但并不引入任何新的接口元素。
将数据模型定义为分类层次结构往往很有用,就像对象数据库将一类对象定义为另一类的子类的方式。这样的数据库可对父类对象执行查询,并在结果中包括子类对象。App Engine 数据存储区本身不支持这类查询,但是可使用 Python SDK 包括的一种机制(PolyModel 类)来实现它。
从 PolyModel 派生的 Model 类可以作为其他 Model 类的基类。使用 all() 和 gql() 方法为这些类创建的查询会在结果中包括子类的实例。
子类可定义父类上不存在的新属性。但是,子类无法覆盖父类的属性定义。(这样做将导致 DuplicateProperty 错误。)
以下是实体和模型中的简单示例,以供参考。注意,PolyModel 类是由 google.appengine.ext.db.polymodel 包提供的。
from google.appengine.ext import db
from google.appengine.ext.db import polymodel
class Contact(polymodel.PolyModel):
phone_number = db.PhoneNumberProperty()
address = db.PostalAddressProperty()
class Person(Contact):
first_name = db.StringProperty()
last_name = db.StringProperty()
mobile_number = db.PhoneNumberProperty()
class Company(Contact):
name = db.StringProperty()
fax_number = db.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.all():
# Returns both p and c.
# ...
for person in Person.all():
# Returns only p.
# ...
PolyModel 不像 Expando 那样支持动态属性。对于 Expando,不存在等同的 PolyModel。
多态性并不是数据存储区的固有特性。相反,多态性是在 PolyModel 类本身中实现的。从 PolyModel 子类创建的所有实体都将以相同的类型存储在数据存储区中,它是根类的名称(例如 Animal)。每个对象都将以名为 'class' 的实体的多值属性的形式存储其类层次结构。当应用程序使用 PolyModel 类的 all() 或 gql() 方法创建查询时,查询将包括对 'class' 属性的过滤条件,使结果限于从该类或任意子类创建的实体。
由于 PolyModel 使用实体属性存储类信息,多态查询的索引必须提供 'class' 属性。隐含的过滤条件是相等过滤条件,可与其他属性上的其他相等过滤条件和不等过滤条件相结合。
注意:PolyModel 仅使用 'class' 属性中类的名称,并非完整路径。可创建具有相同名称的多个节点的类层次结构,例如 A → B 和 A → C → B。对其中一个的查询将返回全部两个的实体。同样,对 A → B → C 和 A → C → B 的查询在功能上是相同的。最好避免创建具有相同名称的多个节点的单个类层次结构。
PolyModel 类的构造函数定义如下:
可以作为其他 Model 类的超类的 Model 类,其查询可包括子类的实例作为结果。与 Model 类似,PolyModel 类必须成为子类才能定义数据实体的类型。
PolyModel 是 Model 的子类,并可继承或覆盖其方法。
参数:
新实体的名称。该名称会成为主键的一部分。如果为 None,将为键使用系统生成的 ID。
key_name 的值不得以数字开头 也绝不能采用 __*__ 的形式。如果您的应用程序使用用户提交的数据来作为数据存储区实体的键名(例如电子邮件地址),则应用程序应先清理该值(例如为其添加“key:”等已知的字符串前缀),使其符合这些要求。
key_name 存储为 Unicode 字符串,str 值转换为 ASCII 文本。
除了由 Model 类定义的类方法外,PolyModel 类还将提供下列类方法:
以元组的形式返回类名称以及类的所有父类的名称。
返回类名称。如果 Python 类的名称发生了更改,则某个类可覆盖此方法,但实体应继续使用原来的类名称。