Python gql内部事务

Python gql内部事务,python,google-app-engine,Python,Google App Engine,Google app engine返回“BadRequestError:事务中只允许祖先查询”。这在代码上下文中是什么意思: class Counter(db.Model): totalRegistrations = db.IntegerProperty(default=0) @db.transactional def countUsers(): counter = Counter.all().get() counter.totalRegistration

Google app engine返回“BadRequestError:事务中只允许祖先查询”。这在代码上下文中是什么意思:

class Counter(db.Model):
        totalRegistrations = db.IntegerProperty(default=0)   

@db.transactional
def countUsers():
    counter = Counter.all().get()
    counter.totalRegistrations = counter.totalRegistrations + 1
    counter.put()
    i = counter.totalRegistrations
    return i

print countUsers()

它只是意味着使用
Counter.all().get()
运行的查询不是祖先查询。在这种情况下,您应该使用从事务方法中提取计数器的查询,如下所示:

@db.transactional
def incrementUsers(counterKey):
    counter = Counter.get(counterKey)
    counter.totalRegistrations = counter.totalRegistrations + 1
    counter.put()
    return counter.totalRegistrations

counterKey = Counter.all(keys_only=True).get()

print incrementUsers(counterKey)

这意味着您首先获得对计数器的引用,但只在事务方法中获取并放入值,从而保证原子性。

注意,您所做的是一种反模式:通过拥有一个需要更新的实体,您将此代码的调用方限制在1QPS左右。此外,您应该使用键名,以避免首先需要查询。另外,永远不要在网络应用程序中使用
print
。嗨,尼克,谢谢你的评论。您能解释一下“使用密钥名以避免查询”的含义吗。我知道这段代码会造成GAE瓶颈,但您是如何提出1QPS限制的?谢谢。如果您只有一个计数器,您可以在创建时指定一个键名。然后,使用
Counter.get\u by_key\u name
在事务中使用指定的名称,避免查询。1QPS限额是记录在案的单个实体组的交易数量下限。将这种瓶颈引入应用程序是一个非常糟糕的主意。