对于ndb.JsonProperty,值从一个实例泄漏到另一个实例

时间:2018-03-03 17:18:29

标签: google-app-engine app-engine-ndb google-app-engine-python

所以,我把讨厌的问题缩小到了这个......

class TestModel(ndb.Model):
    json1 = ndb.JsonProperty(default={})

entity1 = TestModel()
entity1.json1['val1'] = 'added via entity1'

entity2 = TestModel()
entity2.json1['val2'] = 'added via entity2'
logging.warn('entity2.json1 = {}'.format(entity2.json1))

在日志中,我看到了:

... entity2.json1 = {'val2': 'added via entity2', 'val1': 'added via entity1'}

令人惊讶的是,非常危险,我发现在第一个实例entity1中设置的值已泄漏到第二个实例entity2中。

我期望TestModel的第二次实例化为我提供一个“干净”的实例,这是不合理的,特别是因为我default={} JsonProperty?我应该做一些我不喜欢的事情。或者这可能是ndb的错误?

更新:到目前为止我最好的解决方法:始终TestModel(json1={})。但我想我担心如果我们的某个开发人员忘记这样做,我们就可以将一个客户的数据泄露给另一个客户。

更新:似乎已经向Google报告了错误。 35898756表明请求之间可能发生此(错误)行为。它于3年前开放;还在等待解决。

1 个答案:

答案 0 :(得分:1)

对于对这个问题感兴趣的人,我已经找到了一个让我晚上睡得更好的解决方法。它不符合上面的评论,所以我回答了我自己的问题(希望它没问题)......

这看起来似乎是一个错误(见35898756)3岁,很可能不会很快修复。上面的解决方法包括执行TestModel(json1={}) 始终或子类JsonProperty并使用我的自定义类始终,从不使用ndb的类(和我必须重复所有其他类似的属性,如PickleProperty)。这些工作,但担心我,因为项目的每个开发人员都必须在代码库中始终做正确的事情。哈!

所以,这是一个解决方法,意味着"做正确的事情"本地化只是我的模型(更少的代码需要担心)。

class TestModel(ndb.Model):
    json1 = ndb.JsonProperty(default={})

    def __init__(self, **kwargs):
        kwargs.setdefault('json1', {})     # <---- ADDED THIS!
        super(TestModel, self).__init__(**kwargs)

在我的模型的构造函数中,如果它不存在,请添加关键字arg以将属性设置为{}。这似乎可以防止值从一个实例泄漏到另一个实例。