У меня возникли некоторые проблемы в Google App Engine, обеспечивающей правильность моих данных при использовании отношения предка без имен ключей.
Позвольте мне объяснить немного подробнее: у меня есть родительский объект категория , и я хочу создать дочернюю сущность item .Я хотел бы создать функцию, которая принимает имя категории и имя элемента, и создает обе сущности, если они не существуют.Первоначально я создал одну транзакцию и, при необходимости, создал обе транзакции, используя имя ключа, и это работало нормально.Однако я понял, что не хочу использовать имя в качестве ключа, поскольку оно может потребоваться изменить, и я попытался в своей транзакции сделать это:
def add_item_txn(category_name, item_name):
category_query = db.GqlQuery("SELECT * FROM Category WHERE name=:category_name", category_name=category_name)
category = category_query.get()
if not category:
category = Category(name=category_name, count=0)
item_query = db.GqlQuery("SELECT * FROM Item WHERE name=:name AND ANCESTOR IS :category", name=item_name, category=category)
item_results = item_query.fetch(1)
if len(item_results) == 0:
item = Item(parent=category, name=name)
db.run_in_transaction(add_item_txn, "foo", "bar")
Что я нашел, когда попытался запуститьэто то, что App Engine отклоняет это, поскольку не позволяет выполнить запрос в транзакции: Only ancestor queries are allowed inside transactions
.
Рассматривая пример , Google дает о том, как решить эту проблему:
def decrement(key, amount=1):
counter = db.get(key)
counter.count -= amount
if counter.count < 0: # don't let the counter go negative
raise db.Rollback()
db.put(counter)
q = db.GqlQuery("SELECT * FROM Counter WHERE name = :1", "foo")
counter = q.get()
db.run_in_transaction(decrement, counter.key(), amount=5)
Я попытался переместить выборку категории до транзакции:
def add_item_txn(category_key, item_name):
category = category_key.get()
item_query = db.GqlQuery("SELECT * FROM Item WHERE name=:name AND ANCESTOR IS :category", name=item_name, category=category)
item_results = item_query.fetch(1)
if len(item_results) == 0:
item = Item(parent=category, name=name)
category_query = db.GqlQuery("SELECT * FROM Category WHERE name=:category_name", category_name="foo")
category = category_query.get()
if not category:
category = Category(name=category_name, count=0)
db.run_in_transaction(add_item_txn, category.key(), "bar")
Это, казалось бы, сработало, но я обнаружил, когда запустил это с несколькими запросами, которые у меня былиСоздаются дублированные категории, что имеет смысл, поскольку категория запрашивается вне транзакции, и несколько запросов могут создать несколько категорий.
Кто-нибудь знает, как правильно создать эти категории?Я попытался поместить создание категории в транзакцию, но только снова получил ошибку о запросах предков.
Спасибо!
Симон