PolyModel クラスを使用すると、標準の Model クラスよりも柔軟に、ポリモーフィック クエリをサポートするモデルをアプリケーションで定義できます。PolyModel 派生クラスからクエリを作成すると、クエリの結果にそのクラスまたはサブクラスのインスタンスが含まれる場合があります。
これは google.appengine.ext.ndb.polymodel で定義されます。次の例は、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() は Person と Company インスタンスを返します。PolyModel からではなく Model から派生した Contact の場合、各クラスの kind は異なり、Contact.query() は Contact の適切なサブクラスのインスタンスを返しません。
Person インスタンスのみを取得する場合は、Person.query() を使用します。Contact.query(Contact.class_ == 'Person') も使用できます。
PolyModel には通常の Model メソッドだけでなく、便利なクラスメソッドもあります。
_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() によって返される)はサブクラス間で一意である必要があります。