2015-09-26 8 views
7

Django führt ein kaskadiertes Löschen von Modellen mit Fremdschlüsseln als Standard aus. Das heißt, Sie haben einen ForeignKey in A, der auf B zeigt, und Sie löschen B, dann wird A ebenfalls gelöscht.Warum löscht Django kaskadierende Löschungen auf Fremdschlüsseln?

This is known and documented, aber ich habe keine gute Begründung für die Design-Entscheidung gefunden, um es zu einem Standard zu machen, angesichts wie intuitiv es scheint. Weiß jemand, warum es so sein kann?

+0

Ich glaube es liegt daran, dass ein Objekt, das von anderen abhängt, nicht existieren kann, wenn seine Abhängigkeit nicht existiert. Es ist eine Anforderungsbeziehung, dass das abhängige Objekt existiert. Nimm es von Software, ein Programm kann nicht laufen, wenn alle Abhängigkeiten nicht da sind, oder? –

+0

Warum möchten Sie standardmäßig einen zugehörigen Datensatz dort behalten? Die meiste Zeit, wenn Sie den übergeordneten Datensatz löschen, besteht keine Notwendigkeit für das Kind. –

Antwort

10

7 Jahre ...

ein Ticket war offen #7539

Wo es diskutiert werden begann.

Jahren von benjaoming

Jemand eine Diskussion gebeten ... Ich hatte gerade eine Begegnung mit diesem, und was fehlte war ich zu wissen, was in Bezug auf los ist Löschung Kaskadierung, weil es ist ziemlich gefährlich (Sie verlieren Daten !!) und stiehlt viel Zeit. Es zu verhindern, ist jedoch einfach. Überschreiben die delete() -Methode eines Modells und Aufruf von clear() auf die verwandten Fremdschlüssel des Modells ist einfach, und es ist eine manuelle Implementierung, die alle Programmierer verstehen sollten. Aber ich kann an eine andere Alternative denken: Wenn Null = True für den Fremdschlüssel in Frage, warum nicht automatisch SET NULL, wenn die zugehörige Instanz gelöscht wird? Das ist für mich noch "intuitiver" als CASCADE. Immerhin null = True ist etwas, das der Programmierer angibt und hat mit irgendwo in der Implementierung, weshalb er auch keine kaskadierende Löschung einer solchen Beziehung. Wenn on_delete möglich ist, in einem Schlüsselfeld zu setzen, müsste es der Null-Option entsprechen. und zusammen mit dem "intuition argument", das eine 1: 1 Korrespondenz zwischen den beiden Optionen erstellt. Und dann das "logische Argument": Django behandelt seine Logik in Python-Code, nicht in der Datenbank, die als eine einfache Speicher-Engine gehalten wird. Die RESTRICT-Option ist eine Validierung Problem und wird wahrscheinlich in den meisten Fällen auf diese Weise behandelt werden, so dass die Datenbank erzwingen würde redundant wäre. Um es auf Model-Level zu aktivieren könnte ebnen den Weg für einige schöne neue automatische Validierung in ModelForms, so dass ich denke, es klingt wie eine nette Funktion. Wenn all dies implementiert ist, würde ich vorschlagen, die Null-Option aus Schlüssel Felder zu entfernen und es nach on_delete gesetzt haben.

Jahre später wurde die Angelegenheit erneut in der Gruppe diskutiert.

Django-Entwickler (Beiträge selbst Django)
changing the on_delete=CASCADE default

Und dann andere Tickets erstellt wurden #21127 und #21961.

Und wir sind hier angekommen. ForeignKey and OneToOneField on_delete argument

Um das Bewusstsein über kaskadierende Modell Löschen, das on_delete Argument von ForeignKey und OneToOneField zu erhöhen wird in Django 2.0 erforderlich.

Aktualisieren Sie Modelle und vorhandene Migrationen, um das Argument explizit festzulegen. Da der Standardwert models.CASCADE ist, fügen Sie on_delete = models.CASCADE to alle ForeignKey- und OneToOneFields hinzu, die keine andere Option verwenden. Sie können es auch als zweites Positionsargument übergeben, wenn Sie nicht über die Kompatibilität mit älteren Versionen von Django nachdenken. .

+2

Danke für diesen ganzen Kontext! Es ist großartig zu hören, dass Alternativen geplant sind, und ich freue mich zu hören, dass ich nicht alleine bin und denke, dass es albern ist ;-). Ich mag besonders die Idee eines explizit gesetzten on_null Arguments. Irgendeine Idee über die ursprüngliche Begründung dafür, oder ist das in den Wind verloren gegangen? – mallyvai

+0

hahau, ich denke, ist verloren .. :) –

+1

Schön dieses kaskadierende Verhalten, aber es wäre noch schöner, wenn die Python-Methode zum Löschen der untergeordneten Objekte auch aufgerufen würde, anstatt nur eine SQL-Kaskade-Einschränkung auf die DB ... Zum Glück haben wir pre_delete und post_delete Signale! Also pro Tipp: Überschreibe niemals die Löschmethode bei einem Model, sondern benutze stattdessen Signale! (Schade, es funktioniert nicht das gleiche mit Bulk-Create und Bulk-Update ... aber das ist eine andere Geschichte) – gabn88

Verwandte Themen