附註:我們強烈建議建構新應用程式的開發人員使用 NDB 用戶端程式庫,因為 NDB 用戶端程式庫與本用戶端程式庫相較之下有幾個優點,例如能透過 Memcache API 自動將實體加入快取。如果您目前使用的是舊版的 DB 用戶端程式庫,請參閱從 DB 至 NDB 的遷移指南。
Model
類別是資料模型定義的父類別。
Model
應在 google.appengine.ext.db
模組中定義。
簡介
應用程式定義資料模型的方式,是定義將 Model
當做子類別的類別。模型屬性是以類別屬性及 Property
類別例項進行定義。例如:
class Story(db.Model): title = db.StringProperty() body = db.TextProperty() created = db.DateTimeProperty(auto_now_add=True)
應用程式將 Model
類別的子類別例項化,以建立新的資料實體。實體屬性可利用例項屬性或關鍵字引數指派至建構函式。
s = Story() s.title = "The Three Little Pigs" s = Story(title="The Three Little Pigs")
模型子類別名稱會當做 Datastore 實體種類名稱使用。Datastore 保留所有以兩條底線 (__
) 開頭的種類名稱,因此模型子類別不得使用這類名稱。
屬性名稱將做為實體對應屬性的名稱。模型執行個體屬性名稱若以底線 (_
) 開頭將遭到忽略,因此應用程式可利用這類屬性,將資料儲存在並未儲存於 Datastore 的模型執行個體。
Datastore 及模型類別 API 針對屬性名稱及模型執行個體屬性施加多項限制。請參閱不允許使用的屬性名稱瞭解完整說明。
每個實體都有「金鑰」,是代表實體的唯一 ID。金鑰可能包含選用的「金鑰名稱」,是特定種類實體之間的唯一字串。實體種類及金鑰名稱可搭配使用 Key.from_path()
和 Model.get_by_key_name()
方法,以擷取實體。
實體也可能擁有選用的「父項」實體。父項子項關係形成「實體群組」,用於控制 Datastore 之中的交易能力及資料局部性。應用程式在兩個實體之間建立父項子項關係的方式,是將父系實體傳送至子系實體的建構函式,作為 parent
引數。
方法 Model.get_or_insert()
可用於擷取可能不存在的實體,於必要時在 Datastore 之中建立:
keyname = "some_key" s = Story.get_or_insert(keyname, title="The Three Little Pigs")
附註:模型執行個體在 Datastore 之中並沒有對應實體,直到明確或透過 Model.get_or_insert()
首次寫入 (put) 為止。
如需建立屬於模型執行個體資料副本的 dict
,請使用 db.to_dict
函式。
建構函式
Model
類別的建構函式定義如下:
- class Model (parent=None, key_name=None, **kwds)
-
資料模型定義的父類別。
建構期間將呼叫每項屬性的
validate()
方法。前述呼叫的例外狀況將傳播至此建構函式的呼叫者。引數
- parent
- 模型執行個體或實體 (為新實體的父項) 金鑰。
- key_name
-
實體的金鑰名稱。這個名稱會成為主要金鑰的一部分。如果值為
None
,就會使用系統產生的數字 ID 做為金鑰。key_name
的值不得為__*__
形式。金鑰名稱會以 Unicode 字串形式儲存,其中的
str
值會轉換成 ASCII 文字。在此物件呼叫
put()
將「覆寫」具有相同金鑰的任何現有 Datastore 實體。 - kwds
- 例項屬性的初始值,形式為關鍵字引數。每項名稱會對應模型類別定義的屬性。
其他關鍵字引數
- key
-
實體明確的
Key
執行個體。無法與key_name
或parent
搭配使用。如果值為None
,將回到key_name
及parent
行為。使用allocate_ids()
保留新實體數字 ID 時相當實用。key
的值必須為有效的Key
執行個體。在此物件呼叫
put()
將「覆寫」具有相同金鑰的任何現有 Datastore 實體。
類別方法
Model
類別具有下列類別方法:
- Model.get (keys)
-
針對特定金鑰 (或多個金鑰) 擷取模型執行個體 (或多個執行個體)。 金鑰必須代表模型種類實體。如果提供的金鑰並非屬於正確種類,系統就會傳回
KindError
例外狀況。此方法類似於
db.get()
函式,且包含額外的類型檢查。引數
- keys
- 要擷取的實體金鑰、金鑰的字串表示法,或是金鑰或金鑰字串表示法的清單。
- read_policy
- 指定所需資料一致性程度的讀取政策:
- STRONG_CONSISTENCY
- 保證為最新結果,但僅限單一實體群組。
- EVENTUAL_CONSISTENCY
- 可涵蓋多個實體群組,但可能偶爾會傳回過時結果。一般來說,最終一致性查詢的執行速度,比同步一致性查詢更快,但並不保證絕對如此。
注意:全域 (非祖系) 查詢會忽略這個引數。
- deadline
- 在因錯誤而取消之前,等待 Datastore 傳回結果的秒數上限,可接受整數或浮點值。不得高於預設值 (60 秒),但可向下調整來確保特定作業快速失敗 (例如更快將回應傳回給使用者、重試作業、嘗試不同作業,或是將作業新增至工作佇列)。
如果
keys
包含單一金鑰 (或其字串表示法),這個方法會在該金鑰存在於 Datastore 時傳回與金鑰相關的模型執行個體,否則會傳回None
。如果keys
為清單,傳回值為對應的模型執行個體清單,如果指定金鑰沒有實體,則為None
值。另請參閱
db.get()
函式。 - Model.get_by_id (ids, parent=None)
-
擷取模型執行個體 (或多個執行個體) 用於特定數字 ID (或多個數字 ID)。
引數
- ids
- 數字實體 ID,或數字 ID 清單。
- parent
- 要求實體的父系實體,為模型或金鑰形式,如果要求實體沒有父項,則為
None
(預設值)。以單一呼叫要求的多個實體,必須同屬一個父項。 - read_policy
- 指定所需資料一致性程度的讀取政策:
- STRONG_CONSISTENCY
- 保證為最新結果,但僅限單一實體群組。
- EVENTUAL_CONSISTENCY
- 可涵蓋多個實體群組,但可能偶爾會傳回過時結果。一般來說,最終一致性查詢的執行速度,比同步一致性查詢更快,但並不保證絕對如此。
注意:全域 (非祖系) 查詢會忽略這個引數。
- deadline
- 在因錯誤而取消之前,等待 Datastore 傳回結果的秒數上限,可接受整數或浮點值。不得高於預設值 (60 秒),但可向下調整來確保特定作業快速失敗 (例如更快將回應傳回給使用者、重試作業、嘗試不同作業,或是將作業新增至工作佇列)。
如果
ids
包含單一數字 ID,這個方法會在該 ID 存在於 Datastore 時傳回與 ID 相關的模型執行個體,否則會傳回None
。如果ids
為清單,傳回值為對應的模型執行個體清單,如果指定數字 ID 沒有實體,則為None
值。 - Model.get_by_key_name (key_names, parent=None)
-
擷取模型執行個體 (或多個執行個體) 用於特定金鑰名稱 (或多個名稱)。
引數
- key_names
- 金鑰名稱或金鑰名稱清單。
- parent
- 要求實體的父系實體,為模型執行個體或金鑰形式,如果要求實體沒有父項,則為
None
(預設值)。以單一呼叫要求的多個實體,必須同屬一個父項。 - read_policy
- 指定所需資料一致性程度的讀取政策:
- STRONG_CONSISTENCY
- 保證為最新結果,但僅限單一實體群組。
- EVENTUAL_CONSISTENCY
- 可涵蓋多個實體群組,但可能偶爾會傳回過時結果。一般來說,最終一致性查詢的執行速度,比同步一致性查詢更快,但並不保證絕對如此。
注意:全域 (非祖系) 查詢會忽略這個引數。
- deadline
- 在因錯誤而取消之前,等待 Datastore 傳回結果的秒數上限,可接受整數或浮點值。不得高於預設值 (60 秒),但可向下調整來確保特定作業快速失敗 (例如更快將回應傳回給使用者、重試作業、嘗試不同作業,或是將作業新增至工作佇列)。
如果
key_names
包含單一金鑰名稱,這個方法會在該名稱存在於 Datastore 時傳回與名稱相關的模型執行個體,否則會傳回None
。如果key_names
為清單,傳回值為對應的模型執行個體清單,如果指定金鑰名稱沒有實體,則為None
值。 - Model.get_or_insert (key_name, **kwds)
-
嘗試以指定金鑰名稱取得模型種類的實體。如果存在,
get_or_insert()
會直接將其傳回;如果不存在,則會在kwds
中建立、儲存及傳回具有指定種類、名稱和參數的新實體。Get 及之後 (可能) 的 put 運算將納入交易之中,以確保不可部分完成性。這代表
get_or_insert()
絕對不會覆寫現有實體,只有在沒有指定種類及名稱的實體存在時,才會插入新的實體。換句話說,get_or_insert()
與下列 Python 程式碼的功能相同:def txn(key_name, **kwds): entity = Story.get_by_key_name(key_name, parent=kwds.get('parent')) if entity is None: entity = Story(key_name=key_name, **kwds) entity.put() return entity def get_or_insert(key_name, **kwargs): return db.run_in_transaction(txn, key_name, **kwargs) get_or_insert('some key', title="The Three Little Pigs")
引數
- key_name
- 這是實體金鑰的名稱
- kwds
- 具有指定金鑰名稱的執行個體不存在時,傳送至模型類別建構函式的關鍵字引數。如果所需的實體具有父項,就需要
parent
引數。
附註:
get_or_insert()
不接受read_policy
或deadline
引數。方法傳回代表要求實體的模型類別執行個體,不論是否存在或由方法建立。與所有 Datastore 運算一樣,若交易無法完成,此方法可提出
TransactionFailedError
。 - Model.all (keys_only=False)
-
傳回
Query
物件,代表對應至此模型種類的所有實體。查詢物件的方法可於執行查詢前,在查詢套用篩選器及排序順序;詳情請參閱Query
類別頁面。引數
- keys_only
- 查詢應傳回完整實體或是僅傳回金鑰。相較於傳回完整實體的查詢,傳回金鑰的查詢速度較快,使用的 CPU 時間較短。
- Model.gql (query_string, *args, **kwds)
-
針對此模型執行個體執行 GQL 查詢。
引數
- query_string
- GQL 查詢在
SELECT
*
FROM
model
之後的部分 (使用此類別方法時一定包含在內)。 - args
- 位置參數繫結,類似於
GqlQuery()
建構函式。 - kwds
- 關鍵字參數係結,類似於
GqlQuery()
建構函式。
s = Story.gql("WHERE title = :1", "Little Red Riding Hood") s = Story.gql("WHERE title = :title", title="Little Red Riding Hood")
傳回值為
GqlQuery
物件,可用於存取結果。 - Model.kind ()
- 傳回模型的種類,通常是 Model 子類別的名稱。
- Model.properties ()
- 傳回為這個模型類別定義的所有屬性字典。
執行個體方法
模型執行個體的方法如下:
- key ()
-
傳回此模型執行個體的 Datastore
Key
。模型執行個體金鑰包含執行個體的「實體種類」,以及不重複的唯一「ID」。ID 可能是「金鑰名稱」字串 (於執行個體建立時由應用程式明確指派),或是整數「數字 ID」 (於執行個體寫入 (put) 至 Datastore 時由 App Engine 自動指派)。如果在執行個體獲指派 ID 之前呼叫
key()
,系統會傳回NotSavedError
例外狀況。 - put ()
-
將模型執行個體儲存於 Datastore。若模型執行個體為新建且從未儲存,此方法將於 Datastore 建立新的資料實體,否則將以目前屬性值更新資料實體。
方法傳回已儲存實體的金鑰。
若資料無法修訂,系統會傳回
TransactionFailedError
例外狀況。引數
- deadline
- 在因錯誤而取消之前,等待 Datastore 傳回結果的秒數上限,可接受整數或浮點值。不得高於預設值 (60 秒),但可向下調整,確保特定運算快速失敗 (例如更快速傳回回應給使用者、重試運算、嘗試不同運算,或新增運算至工作佇列)。
- delete ()
-
從 Datastore 中刪除模型執行個體。如果執行個體從未寫入 (put) 至 Datastore,則刪除會提出
NotSavedError
例外狀況。引數
- deadline
- 在因錯誤而取消之前,等待 Datastore 傳回結果的秒數上限,可接受整數或浮點值。不得高於預設值 (60 秒),但可向下調整,確保特定運算快速失敗 (例如更快速傳回回應給使用者、重試運算、嘗試不同運算,或新增運算至工作佇列)。
- is_saved ()
-
如果模型執行個體已寫入 (put) 至 Datastore 至少一次,將傳回
True
。此方法僅檢查執行個體自建立後,是否曾寫入至 Datastore 至少一次,並不會檢查執行個體屬性自上次寫入後是否曾經更新。
- dynamic_properties ()
-
傳回為此模型執行個體定義的動態屬性名稱完整清單。這僅適用於
Expando
類別的執行個體。若為非 Expando 模型執行個體,只會傳回空白清單。 - parent ()
-
傳回此執行個體父系實體的模型執行個體;如果此執行個體沒有父項,則傳回
None
。 - parent_key ()
-
傳回此執行個體父系實體的
Key
,如果此執行個體沒有父項,則傳回None
。 - to_xml ()
-
傳回模型執行個體的 XML 表示法。
不允許的屬性名稱
Datastore 及其 API 對實體屬性名稱及模型執行個體屬性施加多項限制。
Datastore 會保留以兩個底線 (__*__
) 為開頭和結尾的所有屬性名稱。Datastore 實體的屬性不可具有此類名稱。
如果 Model
或 Expando
類別的開頭為底線 (_
),Python 模型 API 就會忽略當中的所有屬性。您的應用程式可利用這類屬性,在資料與未儲存至 Datastore 的模型物件之間建立關聯。
最後 Python 模型 API 會使用物件屬性定義模型屬性,而根據預設,Datastore 實體屬性會以物件屬性命名。由於 Model
類別具有多項屬性及方法用於其他用途,因此前述屬性無法用於 Python API 之中的屬性。例如,Model 無法擁有以屬性 key
存取的屬性。
不過,屬性可為屬性建構函式提供 name
引數,為 Datastore 指派與屬性名稱不同的名稱。這樣可讓 Datastore 實體的屬性名稱類似於 Model
類別之中保留的屬性,並於類別中使用不同的屬性名稱。
class MyModel(db.Model): obj_key = db.StringProperty(name="key")
Python API 的 Model
類別保留下列屬性名稱:
|
|