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
例項;如果 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()
所傳回) 不得重複。