2009-06-28 16 views
6

Utilizzo il motore di app di google con django 1.0.2 (e l'helper di django) e mi chiedo come le persone eseguano l'eliminazione ricorsiva. Supponiamo di avere un modello che è qualcosa di simile:Eliminazione ricorsiva nel motore di app di google

 
class Top(BaseModel): 
    pass 

class Bottom(BaseModel): 
    daddy = db.ReferenceProperty(Top) 

Ora, quando elimino un oggetto di tipo 'Top', voglio tutti gli oggetti 'bottom' associati da eliminare pure.

Come ora, quando elimino un oggetto "Top", gli oggetti "Bottom" rimangono e quindi ottengo dati che non appartengono a nessun luogo. Quando si accede al datastore in una vista, io alla fine con:

Caught an exception while rendering: ReferenceProperty failed to be resolved.

ho potuto ovviamente trovare tutti gli oggetti ed eliminarli, ma dato che il mio vero e proprio modello è di almeno 5 livelli di profondità, spero ci sia un modo per assicurarsi che questo possa essere fatto automaticamente.

Ho trovato questo article su come funziona con Java e sembra essere più o meno quello che voglio.

Qualcuno sa come potrei ottenere quel comportamento anche in django?

risposta

6

È necessario implementarlo manualmente, cercando i record interessati e cancellandoli contemporaneamente all'eliminazione del record padre. È possibile semplificare questo, se lo si desidera, sovrascrivendo il metodo .delete() sulla classe genitore per eliminare automaticamente tutti i record correlati.

Per motivi di prestazioni, è quasi certo che si desidera utilizzare query con solo chiave (che consentono di eliminare le chiavi delle entità senza dover recuperare e decodificare le entità effettive) e le eliminazioni batch. Ad esempio:

db.delete(Bottom.all(keys_only=True).filter("daddy =", top).fetch(1000)) 
+0

Fuori interesse, db.delete chiama delete() su ciascuna entità? È diabolicamente ottimizzato, quindi sono un po 'sospettoso che non sia possibile combinare questi due trucchi. Buon punto su keys_only, però. –

+0

No, db.delete() corrisponde direttamente a un singolo RPC che invia tutte le chiavi da eliminare in parallelo. Entity.delete() è semplicemente zucchero sintattico che chiama db.delete (self). –

+1

Non 'db.delete (top.bottom_set)' funziona bene? –

2

In realtà quel comportamento è specifico del GAE. L'ORM di Django simula "ON DELETE CASCADE" su .delete().

So che questa non è una risposta alla tua domanda, ma forse può aiutarti a guardare nei posti sbagliati.

1

Se la gerarchia è solo un piccolo numero di livelli di profondità, allora si potrebbe essere in grado di fare qualcosa con un campo che si presenta come un percorso di file:

daddy.ancestry = "greatgranddaddy/granddaddy/daddy/" 
me.ancestry = daddy.ancestry + me.uniquename + "/" 

genere di cose. Hai bisogno di nomi unici, almeno unici tra fratelli.

Il percorso negli ID oggetto lo fa già, ma IIRC è associato a gruppi di entità, che non è consigliabile utilizzare per esprimere relazioni nel dominio dei dati.

Poi si può creare una query per restituire tutti i discendenti di Granddaddy utilizzando il trucco sottostringa iniziale, in questo modo:

query = Person.all() 
query.filter("ancestry >", gdaddy.ancestry + "\U0001") 
query.filter("ancestry <", gdaddy.ancestry + "\UFFFF") 

Ovviamente questo è inutile se non si può andare bene l'ascendenza in uno StringProperty 500 byte .

2

Riconsiderare la struttura dei dati. Se il rapporto non cambierà mai sulla durata di registrazione, è possibile utilizzare "antenati" caratteristica di GAE:

class Top(db.Model): pass 
class Middle(db.Model): pass 
class Bottom(db.Model): pass 

top = Top() 
middles = [Middle(parent=top) for i in range(0,10)] 
bottoms = [Bottom(parent=middle) for i in range(0,10) for middle in middles] 

Poi query per antenato = top troverà tutti i record di tutti i livelli.Quindi sarà facile cancellarli.

descendants = list(db.Query().ancestor(top)) 
# should return [top] + middles + bottoms 
+0

Bello. Buon uso di list comprehensions. La prima volta che ne vedo uno con due loop! Sembra che sarebbero nell'altro ordine, però, con il ciclo esterno che viene prima. –

Problemi correlati