您需要为实体创建一个模型类。可以通过以下两种方法实现此目的:
- 创建一个定义实体属性的模型类。
- 创建一个不会预先定义实体的 Expando 模型类。
本文档介绍了如何创建上述各种模型类。另外还介绍了如何创建模型钩子,以便应用可以在某种类型的操作之前或之后运行某个代码,例如,在每个 get()
之前。
创建带有属性的模型类
在创建实体之前,您必须创建一个模型类,以定义一个或多个实体属性。例如:
...
其中,您希望每个 Account 实体都具有用户名、用户 ID 和电子邮件属性。
如需查看属性类型的完整列表,请参阅实体属性参考。
创建 Expando 模型类
您并非必须使用预先定义了属性的模型类。名为 Expando
的特殊模型子类会更改其实体的行为,以这种方式分配的任何属性都将保存到数据存储区。请注意,此类属性不能以下划线开头。
下面演示了如何创建 Expando 模型:
...
这会将实体写入数据存储区,其中,foo
属性为整数值 1
,bar
属性为字符串值 'blah'
,重复的 tag
属性为字符串值 'exp'
、'and'
和 'oh'
。这些属性已编入索引,您可以使用此实体的 _properties
属性进行检查:
通过从数据存储区获取值而创建的 Expando
会具备保存在数据存储区中的所有属性值。
应用可以向 Expando
子类添加预定义属性:
...
这为 employee
赋予了一个值为 'Sandy'
的 name
属性,一个值为 None
的 age
属性,以及一个值为 'SF'
的动态属性 location
。
要创建 Expando
子类,并且不希望将其属性编入索引,您可以在子类定义中设置 _default_indexed = False
:
...
您还可以在 Expando
实体上设置 _default_indexed
:此操作会影响设置后分配的所有属性。
另一种实用的方法是,查询 Expando
种类中的某个动态属性。如下所示:
上述查询将无法工作,因为该类的 location 属性没有属性对象。不过,您可以使用 GenericProperty
(Expando
类将其用于动态属性):
使用模型钩子
NDB 提供了轻量级钩子机制。通过定义一个钩子,应用可以在某种类型的操作之前或之后运行某个代码;例如,Model
可能会在每个 get()
之前运行某个函数。
当使用相应方法的同步、异步和多个版本时,便会运行钩子函数。例如,“pre-get”钩子将应用于所有 get()
、get_async()
和 get_multi()
。每个钩子都有 RPC 前和 RPC 后版本。
钩子可用于以下方面:
- 查询缓存
- 审核每个用户的 Cloud Datastore 活动
- 模拟数据库触发器
以下示例演示了如何定义钩子函数:
...
...
如果您将 post-hook 用于异步 API,则可以通过调用 check_result()
、get_result()
或生成(在 tasklet 中)异步方法的 future,来触发钩子。Post hook 不会检查远程过程调用 (RPC) 是否成功;无论失败与否,钩子都会运行。
所有 post-hook 在调用签名末尾都有一个 Future 参数。此 Future
对象包含操作的结果。您可以针对此 Future
调用 get_result()
,以检索结果;get_result()
一定不会受阻,因为在调用钩子时,Future
便已处于完成状态。
在 pre-hook 阻止请求发生期间会引发异常。尽管在 <var>*</var>_async
方法中触发了钩子,但您无法通过在 pre-RPC 钩子中引发 tasklets.Return
来预先执行远程过程调用 (RPC)。