是否可以仅修改ndb数据存储区实体的一个属性?

时间:2014-01-08 19:28:21

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

我有一个具有多个属性的数据存储区实体。每个属性都使用单独的方法更新。但是,每隔一段时间我就会发现一个方法覆盖了一个没有使用旧值修改的属性(Null)。

例如。

class SomeModel(ndb.Model): 
  property1 = ndb.StringProperty()
  property2 = ndb.StringProperty()

def method1(self, entity_key_urlsafe):
  data1 = ndb.Key(urlsafe = entity_key_urlsafe).get()
  data1.property1 = "1"
  data1.put()

数据1实体现在具有property1,其值为" 1"

def method2(self, entity_key_urlsafe):
  data1 = ndb.Key(urlsafe = entity_key_urlsafe).get()
  data1.property2 = "2"
  data1.put()

数据1实体现在具有property2,其值为" 2"

但是,如果这些方法紧密连续运行 - method2似乎用其初始值(Null)覆盖property1。

为了解决这个问题,我一直在使用延迟库,但它不可靠(延迟实体似乎每隔一段时间就消失)或可预测(_countdown时间似乎是足够的指导。

我的问题是:在调用data1.put()时,有没有办法只检索和修改数据存储区实体的一个属性而不覆盖其余属性?即在method2的情况下 - 我是否只能写入property2而不覆盖property1?

2 个答案:

答案 0 :(得分:2)

防止此类覆盖的方法是确保您的更新在事务内部完成。使用NDB,这非常简单 - 只需将@ndb.transactional装饰器附加到您的方法:

@ndb.transactional
def method1(self, entity_key_urlsafe):
  data1 = ndb.Key(urlsafe = entity_key_urlsafe).get()
  data1.property1 = "1"
  data1.put()

关于transactions和NDB的文档没有提供与(较旧的)DB version一样多的背景知识,因此要完全熟悉这些限制和选项,您应该阅读这两者。

答案 1 :(得分:2)

我说

我从未见过对这个或诡计或黑客的提及。 我也认为这样的操作很难存在。 当您对实体执行.put()时,该实体将被序列化然后再写入。

实体是您可以从数据存储区保存或检索的类的实例。 想象一下,如果你有一个auto_now的日期属性?然后会发生什么? 2个保存中的哪一个应该编辑该属性?

虽然你的问题似乎有所不同。您的一个函数首先提交并使其他方法值无效,因为它检索过时的副本,而不是预期的副本。

@ Greg 答案谈及交易。你可能想看看它们。

事务用于并发请求,而不是用于继承。 想象一下,2个用户按下保存按钮同时增加计数器。有交易工作。

@ndb.transactional
def increase_counter(entity_key_urlsafe):
    entity = ndb.Key(urlsafe = entity_key_urlsafe).get()
    entity.counter += 1
    entity.put()

交易将确保计数器正确无误。 尝试提交上述事务的第一个将成功,如果重试开启,则后者必须重试(默认情况下为3)。

虽然继承有所不同。说,我和@Greg建议你改变你使用事务的逻辑,如果你想要解决的问题类似于反例。