2009-06-28 18 views
6

Ich benutze Google App-Engine mit Django 1.0.2 (und der Django-Helfer) und frage mich, wie Menschen rekursive löschen gehen. Angenommen, Sie haben ein Modell, das so etwas wie dieses ist:Rekursives Löschen in Google App-Engine

 
class Top(BaseModel): 
    pass 

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

Nun, wenn ich ein Objekt vom Typ ‚Top‘ löschen, ich will alle zugehörigen ‚Bottom‘ Objekte ebenfalls gelöscht werden.

Wie jetzt, wenn ich ein "Top" -Objekt lösche, bleiben die "Bottom" -Objekte und dann bekomme ich Daten, die nirgends hingehören. Wenn Sie den Datenspeicher in einer Ansicht zugreifen, ich am Ende mit:

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

ich natürlich alle Objekte finden konnten, und löschen Sie sie, aber da mein wirkliches Modell mindestens 5 Ebenen tief ist, ich bin der Hoffnung, einen Weg, es gibt um sicherzustellen, dass dies automatisch durchgeführt werden kann.

Ich habe diese article darüber gefunden, wie es mit Java funktioniert und das scheint ziemlich genau das zu sein, was ich auch will.

Wer weiß, wie ich dieses Verhalten auch im Django bekommen könnte?

Antwort

6

Sie müssen dies manuell implementieren, indem Sie betroffene Datensätze nachschlagen und sie gleichzeitig mit dem Löschen des übergeordneten Datensatzes löschen. Sie können dies auf Wunsch vereinfachen, indem Sie die .delete() -Methode für die Elternklasse überschreiben, um alle zugehörigen Datensätze automatisch zu löschen.

Aus Leistungsgründen möchten Sie fast sicher nur Schlüssel-Abfragen verwenden (damit Sie die Schlüssel von Entitäten abrufen können, ohne die tatsächlichen Entitäten abrufen und dekodieren zu müssen) und Stapel löschen. Zum Beispiel:

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

Interessanterweise ruft db.delete delete() für jede Entität auf? Es ist teuflisch optimiert, daher bin ich etwas misstrauisch, dass man diese beiden Tricks nicht kombinieren kann. Guter Punkt nur auf keys_only. –

+0

Nein, db.delete() entspricht direkt einem einzelnen RPC, der alle zu löschenden Schlüssel parallel sendet. Entity.delete() ist einfach syntaktischer Zucker, der db.delete (self) aufruft. –

+1

Würde 'db.delete (top.bottom_set)' nicht gut funktionieren? –

2

Eigentlich ist dieses Verhalten GAE-spezifisch. Djangos ORM simuliert "ON DELETE CASCADE" auf .delete().

Ich weiß, dass dies keine Antwort auf Ihre Frage ist, aber vielleicht kann es Ihnen helfen, an den falschen Stellen zu suchen.

1

Wenn Ihre Hierarchie nur eine kleine Anzahl von Ebenen tief ist, dann könnten Sie in der Lage sein, etwas mit einem Feld zu tun, wie ein Dateipfad aussieht:

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

Art der Sache. Sie benötigen eindeutige Namen, zumindest einmalig unter den Geschwistern.

Der Pfad in Objekt-IDs tut dies bereits, aber IIRC, der mit Entitätsgruppen verbunden ist, von denen empfohlen wird, sie nicht zum Ausdrücken von Beziehungen in der Datendomäne zu verwenden.

Dann können Sie eine Abfrage erstellen alle Urvater Nachkommen zurückkehren, um den anfänglichen Teilkette Trick, wie folgt aus:

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

Offensichtlich ist dies nützt nichts, wenn Sie nicht die Abstammung in einen 500 Byte String passen .

2

Überprüfen Sie die Datenstruktur. Wenn die Beziehung nie auf der Platte Lebensdauer ändern, könnten Sie „Vorfahren“ -Funktion von GAE verwenden:

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] 

dann für Vorfahren Abfrage = top werden alle Datensätze aus allen Ebenen.So wird es einfach sein, sie zu löschen.

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

Schön. Nette Verwendung von Listenkompressen. Mein erstes Mal sah ich zwei Schleifen! Es sieht so aus, als wären sie in der anderen Reihenfolge, wobei die äußere Schleife zuerst kommt. –