My favorites | 中文(繁體) | Sign in
英文版或許有比此中譯版新的內容

PolyModel 類別

PolyModel 類別是資料模型定義的超級類別,而該資料模型定義本身也可以是其他資料模型定義的超級類別。從 PolyModel 類別產生的查詢可在結果包括類別或其子類別的實例。

PolyModel 是由 google.appengine.ext.db.polymodel 模組所提供。

PolyModel 是 Model 的子類別,並從該類別繼承其類別和實例方法。PolyModel 類別可覆寫多種 Model 方法,但不會使用新的介面元素。

簡介

將資料模型定義為分類階層非常實用,就如同物件資料庫將物件的一個類別定義為另一個物件的子類別一樣。這種資料庫可以在父系類別的物件上執行查詢,並在結果中包括子類別的物件。「應用服務引擎」資料存放區原本不支援此種查詢,但您可以使用 Python SDK 中的機制 (PolyModel 類別) 來實作它。

衍生自 PolyModel 的模型類別可以是其他模型類別的基礎類別。現在使用 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 支援。ExpandoPolyModel 並不相同。

多型態不是資料存放區的原生功能。多型態會在 PolyModel 類別中自我實作。從 PolyModel 類別建立的所有實體都會儲存在資料存放區中,並和相同種類 (根類別名稱) 放在一起 (例如 Animal)。每個物件都會將其類別階層儲存為 'class' 實體的多重值屬性。當應用程式使用 PolyModel 類別的 all()gql() 方法建立查詢時,查詢在 'class' 屬性中的篩選器會限制其結果,讓結果只包含從類別或其他子類別建立的實體。

因為 PolyModel 使用實體的屬性來儲存類別資訊,所以多型態查詢的索引必須使用 'class' 屬性。隱含的篩選器是等式篩選器,可與其他屬性的其他等式篩選器和不等式篩選器結合。

請注意:PolyModel 只會使用 'class' 屬性中的類別名稱,不會使用完整路徑。您可以使用相同名稱建立包含多個節點的類別階層,例如 ABACB。一個查詢將傳回兩個實體。同樣地,查詢 ABCACB 的功能完全相同。您最好可以避免建立包含多個相同名稱之節點的單一類別階層。

建構函式

PolyModel 類別的建構函式定義如下:

class PolyModel(parent=None, key_name=None, **kw)

可以是其他模型類別的超級類別,且其查詢可在結果中包含子類別實體的模型類別。就像 Model 一樣,PolyModel 類別必須是子類別才能定義資料實體的種類。

PolyModel 是 Model 的子類別,並繼承或覆寫其方法。

引數:

parent
實體的 Model 實例或 Key 實例是新實體的父項 (parent)。
key_name

新實體的名稱。名稱會成為主要金鑰的一部分。若為 None,則會使用系統產生的 ID 做為金鑰。

key_name 值的開頭不能是數字,而且不能是 (__*__) 型式。 若您的應用程式以使用者提交的資料做為資料存放區實體金鑰名稱 (例如電子郵件地址),則應用程式要先處理好該值,例如加上已知字串的首碼 (像是「key:」),以符合這些要求。

key_name 會儲存為 Unicode 字串,而 str 值會轉換為 ASCII 文字。

**kw
實例屬性的初始值 (做為 keyword 引數)。每個名稱會與新實例的屬性 (attribute) 相關,且必須與 PolyModel 類別中定義的固定屬性相關。

類別方法

除了 Model 類別定義的類別方法之外,PolyModel 類別還提供下列類別方法:

PolyModel.class_key()

以 tuple 的方式傳回類別名稱和所有父系類別的名稱。

PolyModel.class_name()

傳回類別名稱。如果變更了 Python 類別的名稱,則類別可覆寫此方法,但實體應該繼續使用原始的類別名稱。