使用 ndb.ComputedProperty 非祖先查询确保事务更新成功

Ensuring a transactional update succeeds with ndb.ComputedProperty non-ancestor query

我有一个事务函数,可以按如下方式更新模型实体

@ndb.transactional(xg=True)
def do_something(some_key):
   some_entity = some_key.get()
   some_entity.some_property = "New value"
   some_entity.put()

class TheModel(ndb.Model):
    some_property = ndb.StringProperty()
    blob_key = ndb.BlobKeyProperty()

    @ndb.ComputedProperty
    def md5(self):
        try:
            bi = blobstore.BlobInfo(self.blob_key)
            if bi:
                return bi.md5_hash
            return None
         except:
             logging.error(sys.exc_info())

当我 运行 do_something put 失败时 - 从测试中我可以看出这是由于函数的事务性质造成的。我收集到 blobstore 查询/按键获取导致失败。

是否有既定的方法来确保 ComputedProperties 与事务函数中包含的模型一起工作(其中计算涉及非祖先查询)?

编辑 1: 我用 sys.exc_info() 捕获异常,它 returns

(<type 'exceptions.AttributeError'>, AttributeError("'Key' object has no attribute 'reference'",), <traceback object at 0xf613c968>)

编辑 2: 如果我删除装饰器,则不会发生异常。

事实证明,ndb 有两种方便的方法来克服这个问题。有如下所示的 ndb.in_transaction approach which returns True if the operation is part of a transaction (so I can run or not run the lookup code). The second approach, which I've ended up using is to use the @ndb.non_transactional 装饰器,来自文档的是

Decorator to ensure that a function runs outside a transaction.

class TheModel(ndb.Model):
    some_property = ndb.StringProperty()
    blob_key = ndb.BlobKeyProperty()

    @ndb.ComputedProperty
    @ndb.non_transactional
    def md5(self):
        try:
            bi = blobstore.BlobInfo(self.blob_key)
            if bi:
                return bi.md5_hash
            return None
         except:
             logging.error(sys.exc_info())