Django-Signale vs. überschreibende Speichermethode

89

Ich habe Probleme, meinen Kopf darum zu wickeln. Im Moment habe ich einige Modelle, die ungefähr so ​​aussehen:

 def Review(models.Model)
    ...fields...
    overall_score = models.FloatField(blank=True)

def Score(models.Model)
    review = models.ForeignKey(Review)
    question = models.TextField()
    grade = models.IntegerField()

Eine Überprüfung hat mehrere "Punkte", der Gesamtwert ist der Durchschnitt der Punkte. Wenn eine Bewertung oder ein Ergebnis gespeichert wird, muss ich den Gesamtdurchschnitt neu berechnen. Im Moment verwende ich eine überschriebene Speichermethode. Würde die Verwendung des Signalverteilers von Django Vorteile bringen?

imjoevasquez
quelle

Antworten:

84

Das Speichern / Löschen von Signalen ist im Allgemeinen in Situationen günstig, in denen Sie Änderungen vornehmen müssen, die nicht vollständig spezifisch für das betreffende Modell sind, oder auf Modelle angewendet werden können, die etwas gemeinsam haben, oder für die modellübergreifende Verwendung konfiguriert werden können.

Eine häufige Aufgabe bei überschriebenen saveMethoden ist die automatisierte Generierung von Slugs aus einem Textfeld in einem Modell. Dies ist ein Beispiel für etwas, das, wenn Sie es für eine Reihe von Modellen implementieren müssten, von der Verwendung eines pre_saveSignals profitieren würde , bei dem der Signalhandler den Namen des Slug-Felds und den Namen des Felds verwenden könnte, aus dem der Slug generiert werden soll. Sobald Sie so etwas eingerichtet haben, gilt jede erweiterte Funktionalität, die Sie eingerichtet haben, auch für alle Modelle - z. B. das Nachschlagen der Schnecke, die Sie für den betreffenden Modelltyp hinzufügen möchten, um die Eindeutigkeit sicherzustellen.

Wiederverwendbare Anwendungen profitieren häufig von der Verwendung von Signalen. Wenn die von ihnen bereitgestellten Funktionen auf ein beliebiges Modell angewendet werden können, möchten sie im Allgemeinen (sofern dies nicht unvermeidbar ist) nicht, dass Benutzer ihre Modelle direkt ändern müssen, um davon zu profitieren.

Mit django-mptt habe ich beispielsweise das pre_saveSignal verwendet, um eine Reihe von Feldern zu verwalten, die eine Baumstruktur für das Modell beschreiben, das erstellt oder aktualisiert werden soll, und das pre_deleteSignal, um Baumstrukturdetails für das zu löschende Objekt und dessen Gesamtheit zu entfernen Unterbaum von Objekten davor und sie werden gelöscht. Aufgrund der Verwendung von Signalen müssen Benutzer ihren Modellen keine Methoden hinzufügen oder ändern saveoder deleteMethoden hinzufügen , um diese Verwaltung für sie durchzuführen. Sie müssen django-mptt lediglich mitteilen, welche Modelle sie verwalten sollen.

Jonny Buchanan
quelle
Was ist, wenn der Signalhandler eine Ausnahme auslöst? Ich nehme an, sie sollten keine Ausnahmen auslösen, sonst passen sie nicht gut zusammen. Liege ich falsch?
X-Yuri
19

Du hast gefragt:

Würde die Verwendung des Signalverteilers von Django Vorteile bringen?

Ich fand dies in den Django-Dokumenten:

Überschriebene Modellmethoden werden bei Massenoperationen nicht aufgerufen

Beachten Sie, dass die delete () -Methode für ein Objekt nicht unbedingt aufgerufen wird, wenn Objekte in großen Mengen mit einem QuerySet oder als Ergebnis eines kaskadierenden Löschvorgangs gelöscht werden. Um sicherzustellen, dass die angepasste Löschlogik ausgeführt wird, können Sie die Signale pre_delete und / oder post_delete verwenden.

Leider gibt es keine Problemumgehung beim Erstellen oder Aktualisieren von Objekten in großen Mengen, da weder save (), pre_save noch post_save aufgerufen werden.

Von: Vordefinierte Modellmethoden überschreiben

guettli
quelle
2
Django Admin-Listenansicht verwendet Massenlöschung ... war verwirrt, bis auf diesen Leckerbissen stieß.
N. Balauro
7
Außerdem heißt es: "Leider gibt es keine Problemumgehung beim Erstellen oder Aktualisieren von Objekten in großen Mengen, da weder save (), pre_save noch post_save aufgerufen werden." - Ich denke also nicht, dass dies ein Kompromiss zwischen diesen Methoden ist.
Cory
Dies gilt für beide Methoden. Ist die Antwort dann: "Nein, es hat keinen Vorteil, Signale zu verwenden, anstatt die saveMethode zu überschreiben "?
Flimm
3

Wenn Sie Signale verwenden, können Sie die Bewertungsbewertung jedes Mal aktualisieren, wenn das zugehörige Bewertungsmodell gespeichert wird. Aber wenn ich solche Funktionen nicht brauche, sehe ich keinen Grund, dies zu signalisieren, das ist ziemlich modellbezogen.

Dmitry Shevchenko
quelle
2

Es ist eine Art Denormalisierung. Schauen Sie sich diese hübsche Lösung an . Definition des In-Place-Kompositionsfelds.

Alex Koshelev
quelle
1

Kleiner Zusatz aus Django-Dokumenten zum Massenlöschen ( .delete()Methode für QuerySetObjekte):

Beachten Sie, dass dies nach Möglichkeit nur in SQL ausgeführt wird und daher die delete () -Methoden einzelner Objektinstanzen nicht unbedingt während des Prozesses aufgerufen werden. Wenn Sie eine benutzerdefinierte delete () -Methode für eine Modellklasse bereitgestellt haben und sicherstellen möchten, dass diese aufgerufen wird, müssen Sie Instanzen dieses Modells "manuell" löschen (z. B. indem Sie ein QuerySet durchlaufen und delete () aufrufen jedes Objekt einzeln) anstatt die Bulk-Methode delete () eines QuerySet zu verwenden.

https://docs.djangoproject.com/de/1.11/topics/db/queries/#deleting-objects

Und Massenaktualisierung ( .update()Methode für QuerySetObjekte):

Stellen Sie schließlich fest, dass update () ein Update auf SQL-Ebene ausführt und daher keine save () -Methoden für Ihre Modelle aufruft und auch keine pre_save- oder post_save-Signale ausgibt (die eine Folge des Aufrufs von Model.save () sind). )). Wenn Sie eine Reihe von Datensätzen für ein Modell mit einer benutzerdefinierten save () -Methode aktualisieren möchten, durchlaufen Sie diese und rufen Sie save () auf.

https://docs.djangoproject.com/de/2.1/ref/models/querysets/#update

Valex
quelle
Gilt das nicht für beide?
Flimm