所以,我把讨厌的问题缩小到了这个......
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年前开放;还在等待解决。
答案 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以将属性设置为{}。这似乎可以防止值从一个实例泄漏到另一个实例。