2

我想要一个像这样的方法:

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.{prop}为更改的属性显式更新每个属性吗?

迭代.properties()并浮现.dynamic_properties()在脑海中。实体是否有任何其他可能需要同步的状态?

4

2 回答 2

2

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

@静态方法:

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(()

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

  • 避免在同一方法中使用对自身的引用和对实体的引用。当您将其视为“难闻的气味”模式时,您是对的。
  • 考虑使用 ndb 而不是 db。这是 db 的一个很好的演变,并且与您当前存储的对象兼容。
于 2013-05-20T20:03:33.557 回答
1

您对交易有正确的方法:https ://developers.google.com/appengine/docs/python/datastore/transactions#Uses_​​for_Transactions

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

以下是 Python 大师本人关于如何更新多个实体的一些关于 SO 的代码:部分更新 App Engine 实体

于 2013-05-17T21:05:25.407 回答