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()
によって返される)はサブクラス間で一意である必要があります。