交易变更GAE实体是否可能?

时间:2013-05-06 17:06:30

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

我希望有一个方法:

class Counter(db.Model):
  n = db.IntegerProperty()

  @db.transactional
  def increment(self):
    entity = db.get(self.key())
    entity.n += 1
    self.n = entity.n
    db.put(entity)

除了我的内容之外,可能会涉及到更多属性以及一些关于哪些属性在何时更新的逻辑。使用'self'设置每次更改为'entity'后,似乎都是多余且容易出错的。

我可以以某种方式执行此操作,而无需为更改的属性明确更新每个self.{prop}吗?

考虑通过.properties().dynamic_properties()进行迭代。实体是否有可能需要同步的任何其他状态?

2 个答案:

答案 0 :(得分:2)

将此方法作为@classmethod(无自我)运行,或跳过'get'。一旦你拥有'自我',就没有必要得到。

@staticmethod:

class Counter(db.Model):
  n = db.IntegerProperty()

  @staticmethod
  @db.transactional
  def increment(key):
    entity = db.get(key)
    entity.n += 1
    db.put(entity)

这样你就可以避免让self和变量引用同一个实体。

如果您仍然希望使用counter.increment()而不是Counter.increment(counter.key()),则另一种有效的方法是在调用方法中启动事务。

class Counter(db.Model):
  n = db.IntegerProperty()

  def increment(self):
    self.n += 1
    db.put(entity)

# Wherever the code is using Counter.
@db.transactional
def main_method(key):
  entity = db.get(key)
  entity.increment(()

我想建议的两条主要信息:

  • 避免在同一方法中使用对self的引用和对实体的引用。当你认为这是一种“难闻的气味”模式时,你是对的。
  • 考虑使用ndb而不是db。这是db的一个很好的演变,并且与你当前存储的对象兼容。

答案 1 :(得分:1)

您有关于交易的正确方法:https://developers.google.com/appengine/docs/python/datastore/transactions#Uses_for_Transactions

您的问题似乎更多是关于一次更新多个实体,以及是否存在任何“隐藏”属性。不,同步没有隐藏的属性。

以下是Python大师自己关于如何更新多个实体的一些代码:Partly update App Engine entity