I have few problems with the Google App Engine, which guarantees the correctness of my data when using relationships between ancestors without key names.
Let me explain a little more: I have a parent category object and I want to create a child item object . I would like to create a function that takes a category name and an element name and creates both entities if they do not exist. Initially, I created one transaction and created it as in a transaction, if necessary, using the key name, and this worked fine. However, I realized that I did not want to use this name as a key, as this might need to be changed, and I tried to do this in my transaction:
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")
What I discovered when trying to run it - is that App Engine rejects it, because it does not allow you to run a query in the transaction: Only ancestor queries are allowed inside transactions.
Looking at an example Google gives on how to solve this problem:
def decrement(key, amount=1):
counter = db.get(key)
counter.count -= amount
if counter.count < 0:
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")
, , , , , , , , , .
- , ? , .
!