我想创建一个正确的post_create(也是post_get和post_put)钩子,类似于我在我的应用程序的DB版本上的钩子。
不幸的是我不能使用has_complete_key。
这个问题众所周知:模型中缺少is_saved。
现在我已经像这样实现了它:
class NdbStuff(HooksInterface):
def __init__(self, *args, **kwds):
super(NdbStuff, self).__init__(*args, **kwds)
self._is_saved = False
def _put_async(self, post_hooks=True, **ctx_options):
""" Implementation of pre/post create hooks. """
if not self._is_saved:
self._pre_create_hook()
fut = super(NdbStuff, self)._put_async(**ctx_options)
if not self._is_saved:
fut._immediate_callbacks.insert(
0,
(
self._post_create_hook,
[fut],
{},
)
)
self._is_saved = True
if post_hooks is False:
fut._immediate_callbacks = []
return fut
put_async = _put_async
@classmethod
def _post_get_hook(cls, key, future):
obj = future.get_result()
if obj is not None:
obj._is_saved = True
cls._post_get(key, future)
def _post_put_hook(self, future):
if future.state == future.FINISHING:
self._is_saved = True
else:
self._is_saved = False
self._post_put(future)
除了post_create钩子之外的所有东西似乎都有效。
每次使用put_async而不先检索对象时都会触发post_create。
我真的很感激如何在创建对象后只触发一次post_create_hook。
答案 0 :(得分:2)
我不确定你为什么要创建NDBStuff类。
如果您创建类的实例,并且想跟踪_is_saved
或类似的东西,请使用工厂来控制属性的创建和设置,在这种情况下跟踪_is_new更有意义例如。
class MyModel(ndb.Model):
some_prop = ndb.StringProperty()
def _pre_put_hook(self):
if getattr(self,'_is_new',None):
self._pre_create_hook()
# do something
def _pre_create_hook(self):
# do something on first save
log.info("First put for this object")
def _post_create_hook(self, future):
# do something
def _post_put_hook(self, future);
if getattr(self,'_is_new', None):
self._post_create_hook(future)
# Get rid of the flag on successful put,
# in case you make some changes and save again.
delattr(self,'_is_new')
@classmethod
def factory(cls,*args,**kwargs):
new_obj = cls(*args,**kwargs)
settattr(new_obj,'_is_new',True)
return new_obj
然后
myobj = MyModel.factory(someargs)
myobj.put()
myobj.some_prop = 'test'
myobj.put()
将在第一次放置时调用_pre_create_hook,而不是在第二次放置。
始终通过工厂创建实体,然后您将始终调用_pre_create_hook执行。
这有意义吗?