模型類別

附註:強烈建議建構新應用程式的開發人員使用 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_nameparent。若為 None,將回到 key_nameparent. 行為。使用 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_policydeadline 引數。

方法傳回代表要求實體的模型類別執行個體,不論是否存在或由方法建立。與所有 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 自動指派。執行個體之前的呼叫 key() 已指派 ID 提出 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 表示法。

符合 AtomData 規格的屬性值。

不允許的屬性名稱

Datastore 及其 API 對實體屬性名稱及模型執行個體屬性施加多項限制。

Datastore 會保留以兩條底線 (__*__) 作為開頭及結尾的所有屬性名稱。Datastore 實體不得擁有使用前述名稱的屬性。

Python 模型 API 會忽略 ModelExpando 類別以底線 (_) 開頭的所有屬性。您的應用程式可利用這類屬性,在資料與未儲存至 Datastore 的模型物件之間建立關聯。

最後 Python 模型 API 會使用物件屬性定義模型屬性,依據預設 Datastore 實體屬性會以屬性命名。由於 Model 類別具有多項屬性及方法用於其他用途,因此前述屬性無法用於 Python API 之中的屬性。例如 Model 無法擁有以屬性 key 存取的屬性。

不過屬性可為 Datastore 指派與屬性名稱不同的名稱,向屬性提供 name 引數。這樣可讓 Datastore 實體的屬性名稱類似於 Model 類別之中保留的屬性,並於類別使用不同的屬性名稱。

class MyModel(db.Model):
  obj_key = db.StringProperty(name="key")

Python API 的 Model 類別保留下列屬性名稱:

  • all
  • app
  • copy
  • delete
  • entity
  • entity_type
  • fields
  • from_entity
  • get
  • gql
  • instance_properties
  • is_saved
  • key
  • key_name
  • kind
  • parent
  • parent_key
  • properties
  • put
  • setdefault
  • to_xml
  • update
本頁內容對您是否有任何幫助?請提供意見:

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

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