Ho riscontrato un po 'di problemi in Google App Engine, assicurandomi che i miei dati siano corretti quando si utilizza una relazione antenato senza nomi chiave.Come posso garantire l'integrità dei dati per gli oggetti nel motore di app di google senza utilizzare i nomi chiave?
Mi spiego un po 'di più: ho una controllante categoria, e voglio creare un'entità figlio voce. Mi piacerebbe creare una funzione che prende il nome di una categoria e il nome di una voce e crea entrambe le entità se non esistono. Inizialmente ho creato una transazione e creato entrambi nella transazione, se necessario, utilizzando un nome chiave, e questo ha funzionato bene. Tuttavia, mi sono reso conto che non volevo usare il nome come chiave come può essere necessario cambiare, e ho cercato nel mio transazione per fare questo:
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")
Quello che ho trovato quando ho provato a correre questo è tale App Engine lo rifiuta poiché non consente di eseguire una query in una transazione: Only ancestor queries are allowed inside transactions
.
Guardando il example Google dà su come affrontare questo:
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)
ho tentato di spostare il mio prendere della categoria a prima che la transazione:
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")
questo apparentemente ha funzionato, ma io trovato quando ho eseguito questo con un numero di richieste che ho creato categorie duplicate, che ha senso, come la query viene interrogata al di fuori della transazione e più richieste potrebbero creare più categorie.
Qualcuno ha idea di come sia possibile creare correttamente queste categorie? Ho provato a mettere la creazione della categoria in una transazione, ma ho ricevuto di nuovo l'errore sulle query degli antenati.
Grazie!
Simon
Stai cercando di evitare di utilizzare i nomi chiave per le categorie? Il modo standard per garantire l'unicità è usando db.get_or_insert (parent, key_name). – mahmoud
Sì, il motivo per cui sto evitando è perché il nome della categoria può cambiare, e se cambio il nome ma ho la chiave come il vecchio nome temo che le cose saranno molto confuse ... – Simon