是否可以使用NDB确定模型是否在数据存储区中持久存在?

Ser*_*gey 14 python google-app-engine

我正在迁移db.Modelndb.Model.在完成此迁移之前我必须解决的唯一问题是没有Model.is_saved方法.我已经db.Model.is_saved在我的应用程序中用于确定是否必须在put/ 上更新分片计数器delete,以检查创建实体上的冲突密钥等.

文档说ndb.Model没有is_saved方法的等价物.我可以重新实现一些用例get_or_insert而不是is_saved.但不是全部.

作为一个肮脏的黑客,我可以_in_memory_instance通过调用构造函数为我创建的每个实例设置标记.但它并没有解决我的问题.我仍然必须至少在每次put()通话后更新此标志.

问题是:有没有更好的方法来确定模型是否在数据存储区中持久存在而没有额外的数据存储区命中?

编辑1:忘记提及:所有实体都有钥匙所以检查Model._has_complete_key()对我不起作用.

编辑2:在讨论之后https://groups.google.com/d/topic/google-appengine/Tm8NDWIvc70/discussion似乎是解决我的问题的唯一方法是使用_post_get_hook/ _post_put_hook.我想知道为什么这样一个微不足道的东西没有被包含在官方API中.

编辑3:我最终得到了所有模型的下一个基类.现在我可以保持我的代码库(几乎)不受影响:

class BaseModel(ndb.Model):

    @classmethod
    def _post_get_hook(cls, key, future):
        self = future.get_result()
        if self:
            self._is_saved = bool(key)

    def _post_put_hook(self, future):
        self._is_saved = future.state == future.FINISHING

    def is_saved(self):
        if self._has_complete_key():
            return getattr(self, "_is_saved", False)
        return False
Run Code Online (Sandbox Code Playgroud)

Gui*_*sum 12

要在NDB中获得相同类型的状态,您需要组合使用post-get-hook和post-put-hook来设置标志.这是一个有效的例子:

class Employee(ndb.Model):
  <properties here>

  saved = False  # class variable provides default value

  @classmethod
  def _post_get_hook(cls, key, future):
    obj = future.get_result()
    if obj is not None:
      # test needed because post_get_hook is called even if get() fails!
      obj.saved = True

  def _post_put_hook(self, future):
    self.saved = True
Run Code Online (Sandbox Code Playgroud)

没有必要检查未来的状态 - 当调用任何一个钩子时,未来总会有结果.这是因为钩子实际上是对未来的回调.但是,需要检查其结果是否为无!

PS:在事务内部,只要put()调用返回就会调用钩子; 交易的成败不会影响他们.有关在成功提交后运行挂钩的方法,请参阅https://developers.google.com/appengine/docs/python/ndb/contextclass#Context_call_on_commit.

  • 如[here](https://code.google.com/p/appengine-ndb-experiment/issues/detail?id=211)所述,这对于通过queries/gql检索的实体不起作用,因为未调用_post_get_hook在他们身上,还没有等同的回调查询. (5认同)