PolyModel 類別

附註:強烈建議建構新應用程式的開發人員使用 NDB 用戶端程式庫;相較於此用戶端程式庫,NDB 用戶端程式庫有幾項優點,例如能透過 Memcache API 自動快取實體。如果您目前使用的是舊版 DB 用戶端程式庫,請參閱 DB 至 NDB 遷移指南

有些資料模型定義本身可以是其他資料模型定義的超類別,而 PolyModel 類別是這類資料模型定義的超類別。如果是透過 PolyModel 類別產生的查詢,其結果可能是該類別或其任何子類別的例項。

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

PolyModel 是 Model 的子類別,會沿用 Model 類別的類別和例項方法。PolyModel 類別會覆寫 Model 的幾種方法,但不會導入任何新的介面元素。

簡介

將資料模型定義為分類階層 (如同物件資料庫可將某一物件類別定義為其他類別的子類別),往往可帶來好處。這類資料庫可對父項類別的物件執行查詢,並在結果中加入子類別的物件。App Engine 資料儲存庫並未針對這種查詢提供原生支援,但您可以使用 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 類別本身中實作。透過 PolyModel 子類別建立的實體全都是以相同種類儲存在資料儲存庫中,而其種類就是根類別的名稱 (例如 Animal)。每個物件會將其類別階層儲存為 'class' 實體的多值屬性。當應用程式使用 PolyModel 類別的 all()gql() 方法建立查詢時,查詢會在 'class' 屬性中加入篩選器,讓結果只包含透過該類別或任何子類別建立的實體。

由於 PolyModel 會使用實體屬性來儲存類別資訊,因此多型查詢的索引必須配合 'class' 屬性。系統採用的篩選器是等式篩選器,並可與其他等式篩選器和不等式篩選器結合,以用於其他屬性。

注意:PolyModel 只會使用 'class' 屬性中的類別名稱,而不會使用完整路徑。您可以使用多個名稱相同的節點來建立多個類別階層,例如 ABACB。對其中一個階層執行查詢會傳回兩者的實體。同樣地,對 ABCACB 執行的查詢也有相同作用。建議您避免使用多個名稱相同的節點來建立單一類別階層。

PolyModel 不支援覆寫子類別中的屬性模型定義。如果子類別嘗試重新定義超類別中定義的屬性,類別定義會發生 DuplicatePropertyError

PolyModel 支援多重沿用,包括沿用超類別相同的多個類別 (「鑽石」沿用)。如有兩個類別分別針對相同屬性定義了不同屬性模型定義,則類別不得沿用這兩個類別,否則會發生 DuplicatePropertyError。不過,如有兩個類別繼承了相同超類別的屬性模型定義,類別就可繼承這兩個類別。

PolyModelExpando 相同,不支援動態屬性。Expando 沒有對等的 PolyModel

建構函式

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

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

模型類別可以是其他模型類別的超類別,且其查詢結果可包含子類別的例項。如同 Model,PolyModel 類別必須變成子類別才能定義資料實體的種類。

PolyModel 是 Model 的子類別,會沿用或覆寫 Model 類別的方法。

引數

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

新實體的名稱。這個名稱會成為主要金鑰的一部分。如果值為 None,金鑰會使用系統產生的 ID。

key_name 值的開頭不得為數字,且格式不得為 __*__。如果您的應用程式是以使用者提交的資料做為資料儲存庫實體金鑰名稱 (例如電子郵件地址),應用程式應先對值進行處理以滿足這些要求,例如在前方加上「key:」等已知字串。

key_name 是以 Unicode 字串形式儲存,str 值會轉換成 ASCII 文字。

**kwds
例項屬性的初始值,形式為關鍵字引數。每個名稱會對應到新例項的屬性,且必須對應到 PolyModel 類別中定義的固定屬性。

類別方法

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

PolyModel.class_key()

傳回類別的名稱和所有父項類別的名稱,以元組表示。

PolyModel.class_name()

傳回類別的名稱。如果 Python 類別的名稱有所異動,類別可覆寫這個方法,但實體應繼續使用原始類別名稱。

本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
Python 2 適用的 App Engine 標準環境