Model 类

注意强烈建议构建新应用的开发者使用 NDB 客户端库,它与 DB 客户端库相比具有多项优势,例如可通过 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 和 Model Class API 对属性名称和模型实例特性实施若干限制。有关完整说明,请参阅禁用的属性名称

每个实体都有一个该键是代表实体的唯一标识符。键可以包含可选的键名(给定种类的实体中非重复的字符串)。实体的种类和键名可用于 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")

注意:直到首次写入 (put) 模型实例(显式或通过 Model.get_or_insert()),模型实例才会在 Datastore 中有相应的实体。

如需创建作为模型实例数据副本的 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
实例属性的初始值,作为关键字参数。每个名称都与 Model 类中定义的属性对应。

其他关键字参数

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 的模型实例。

参数

ids
数字实体 ID 或数字 ID 列表。
parent
所请求实体的父实体(模型或键);如果所请求实体没有父实体,则为 None(默认值)。一个调用所请求的多个实体必须全部具有相同的父实体。
read_policy
指定所需的数据一致性级别的读取政策:
STRONG_CONSISTENCY
保证返回最新的结果,但仅限于单个实体组
EVENTUAL_CONSISTENCY
可以跨越多个实体组,但有时可能会返回过时的结果。通常,最终一致性查询比强一致性查询的运行速度更快,但并不保证始终如此。

注意:全局(非祖先)查询会忽略此参数。

deadline
在使用错误代码取消查询之前,等待 Datastore 返回结果的最长时间(以秒为单位)。接受整数或浮点值。设置的值不能高于默认值(60 秒),但可以向下调整,以确保特定操作快速失败(例如,更快地向用户给出响应、重试操作、尝试其他操作,或将该操作添加到任务队列)。

假如 ids 由单个数字 ID 组成,如果 Datastore 中存在此 ID,则此方法返回与此 ID 关联的模型实例,否则返回 None。如果 ids 是一个列表,则返回值是模型实例的相应列表,其中 None 值表示给定数字 ID 不存在实体。

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
SELECT * FROM model 后面的 GQL 查询部分(使用本类方法即暗示此点)。
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

模型实例的键包括实例的实体种类以及唯一标识符。标识符可以是创建实例时由应用显式分配的键名字符串,也可以是将实例写入 (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 表示形式。

属性值符合 AtomData 规范。

禁止使用的属性名称

Datastore 及其 API 对实体属性名称和模型实例特性实施若干限制。

Datastore 保留所有以两个下划线字符开头和结尾 (__*__) 的属性名称。Datastore 实体的属性不能使用这样的名称。

Python 模型 API 会忽略以一个下划线字符 (_) 开头的 ModelExpando 类的所有特性。应用可以使用这些特性将数据与未保存到 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 类保留以下属性名称:

  • 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