google-app-engine - 在 App Engine 上,如何使 ndb 属性一旦设置就不可变?

标签 google-app-engine python-2.7 google-cloud-datastore app-engine-ndb

这似乎是一个常见的要求,它是内置的,但无论如何:如果您有一个像下面这样的模型,如何阻止 eggs 属性在设置后发生变异?

class Spam(ndb.Model):

    eggs = ndb.StringProperty()

目标是让属性不是必需的,因此它默认为None,但一旦它从None发生变异,对于上述情况下的字符串,它永远不能再次更改,但任何有关定义不可变属性的见解将不胜感激。

我曾考虑过使用 ndb.Propertyvalidator 参数来传入函数;请参阅下面的答案,了解为什么这在这里不起作用。它对于理解所涉及的对象和命名空间很有用。

最佳答案

一种不需要使用自定义属性的方法是使用 Hook ,请参阅文档 https://developers.google.com/appengine/docs/python/ndb/modelclass#Model__post_get_hook

您将使用 _post_get_hook(cls, key, future)_pre_put_hook(self)

_post_get_hook中,您将存储属性的原始值 在 _pre_put_hook 中,您将检查它是否与原始值相同,除非原始值是 None

class Spam(ndb.Model):

    eggs =  ndb.StringProperty()

    @classmethod
    def _post_get_hook(cls,key,future):
        obj = future.get_result()
        obj._my_eggs_prop = obj.eggs

    def _pre_put_hook(self):
        if hasattr(self,'_my_eggs_prop'):
            if self.eggs != self._my_eggs_prop:
               if self._my_eggs_prop != None:
                    # do some logging.
                    raise ValueError
        else:
            setattr(self,'_my_eggs_prop',self.eggs)
            # if the saved value doesn't exist, create it and store
            # the value in case an update occurs after the initial put
            # this also means the object was created and not get() 

这是一个工作示例

s~lightning-catfish> import spam
s~lightning-catfish> x = spam.Spam(id='canned')
s~lightning-catfish> x.eggs = 'green'
s~lightning-catfish> x.put()
Key('Spam', 'canned')
s~lightning-catfish> y = x.key.get()
s~lightning-catfish> y._my_eggs_prop
u'green'
s~lightning-catfish> y.eggs = 'blue'
s~lightning-catfish> y.put()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/timh/google_appengine/google/appengine/ext/ndb/model.py", line 3232, in _put
    return self._put_async(**ctx_options).get_result()
  File "/home/timh/google_appengine/google/appengine/ext/ndb/model.py", line 3247, in _put_async
    self._pre_put_hook()
  File "spam.py", line 18, in _pre_put_hook
    raise ValueError
ValueError

这种方法的缺点是您可以更改其中的属性依赖以获取一些额外的代码,然后只有在执行 put 时才发现它。然而,这可能并没有那么糟糕,因为理论上您不应该有任何代码在更改属性后对其进行修改。因此您想要记录并追踪这种情况是如何发生的。或者,您可以将该值重置为原始设置,但随后会保留不正确的代码。

自定义属性需要更多考虑;-)

关于google-app-engine - 在 App Engine 上,如何使 ndb 属性一旦设置就不可变?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20672561/

相关文章:

python - 如何抑制正在导入的模块的标准输出日志输出?

python - 按键查询模型

python - 如何向 Google 数据存储 StringListProperty 添加选项?

google-app-engine - 作为生产平台的 Google App Engine

java - GCP App 引擎上未找到 logback xml 文件异常

python - 又是 : UnicodeEncodeError: ascii codec can't encode

java - 对 DataStore 异常执行查询

python - Google App Engine 中的 key 生成

java - 在 Android 应用程序中从 Google 云存储读取文件

python - Python中的'//'运算符没有返回正确的解决方法