Google App Engine NDB post_create hook

时间:2015-04-07 08:31:32

标签: python google-app-engine google-cloud-datastore

我想创建一个正确的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。

1 个答案:

答案 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执行。

这有意义吗?