Ich bin mit Django ziemlich vertraut, habe aber kürzlich festgestellt, dass es eine on_delete=models.CASCADE
Option für die Modelle gibt. Ich habe nach der gleichen Dokumentation gesucht, konnte aber nichts weiter finden als:
In Django 1.9 geändert:
on_delete
kann jetzt als zweites Positionsargument verwendet werden (zuvor wurde es normalerweise nur als Schlüsselwortargument übergeben). Dies wird in Django 2.0 ein erforderliches Argument sein.
from django.db import models
class Car(models.Model):
manufacturer = models.ForeignKey(
'Manufacturer',
on_delete=models.CASCADE,
)
# ...
class Manufacturer(models.Model):
# ...
pass
Was macht on_delete? ( Ich denke, die Aktionen müssen ausgeführt werden, wenn das Modell gelöscht wird )
Was macht models.CASCADE
das ( Hinweise in der Dokumentation )
Welche anderen Optionen stehen zur Verfügung ( wenn meine Vermutung richtig ist )?
Wo befindet sich die Dokumentation dazu?
python
django
django-models
Alles ist gut
quelle
quelle
Antworten:
Dies ist das Verhalten, das angewendet werden muss, wenn das referenzierte Objekt gelöscht wird. Es ist nicht spezifisch für Django, dies ist ein SQL-Standard.
Es gibt 6 mögliche Maßnahmen, wenn ein solches Ereignis eintritt:
CASCADE
: Wenn das referenzierte Objekt gelöscht wird, löschen Sie auch die Objekte, auf die verwiesen wird (Wenn Sie beispielsweise einen Blog-Beitrag entfernen, möchten Sie möglicherweise auch Kommentare löschen). SQL-Äquivalent :CASCADE
.PROTECT
: Verbieten Sie das Löschen des referenzierten Objekts. Um es zu löschen, müssen Sie alle Objekte löschen, die manuell darauf verweisen. SQL-Äquivalent :RESTRICT
.SET_NULL
: Setzen Sie den Verweis auf NULL (erfordert, dass das Feld nullwertfähig ist). Wenn Sie beispielsweise einen Benutzer löschen, möchten Sie möglicherweise die Kommentare behalten, die er in Blog-Posts gepostet hat, aber sagen, dass sie von einem anonymen (oder gelöschten) Benutzer gepostet wurden. SQL-Äquivalent :SET NULL
.SET_DEFAULT
: Legen Sie den Standardwert fest. SQL-Äquivalent :SET DEFAULT
.SET(...)
: Stellen Sie einen bestimmten Wert ein. Dieser ist nicht Teil des SQL-Standards und wird vollständig von Django verwaltet.DO_NOTHING
: Wahrscheinlich eine sehr schlechte Idee, da dies zu Integritätsproblemen in Ihrer Datenbank führen würde (Verweis auf ein Objekt, das tatsächlich nicht vorhanden ist). SQL-Äquivalent :NO ACTION
.Quelle: Django-Dokumentation
Siehe auch die Dokumentation von PostGreSQL zum Beispiel.
In den meisten Fällen
CASCADE
ist das erwartete Verhalten, aber für jeden ForeignKey sollten Sie sich immer fragen, was das erwartete Verhalten in dieser Situation ist.PROTECT
undSET_NULL
sind oft nützlich. WennCASCADE
Sie festlegen, wo dies nicht der Fall sein soll, können Sie möglicherweise Ihre gesamte Datenbank in Kaskade löschen, indem Sie einfach einen einzelnen Benutzer löschen.Zusätzlicher Hinweis zur Verdeutlichung der Kaskadenrichtung
Es ist lustig zu bemerken, dass die Richtung der
CASCADE
Aktion für viele Menschen nicht klar ist. Eigentlich ist es lustig zu bemerken, dass nur dieCASCADE
Aktion nicht klar ist. Ich verstehe, dass das Kaskadenverhalten verwirrend sein kann, aber Sie müssen denken, dass es die gleiche Richtung wie jede andere Aktion ist . Wenn Sie also das Gefühl haben, dass Ihnen dieCASCADE
Richtung nicht klar ist, bedeutet dies tatsächlich, dass Ihnen dason_delete
Verhalten nicht klar ist.In Ihrer Datenbank wird ein Fremdschlüssel im Wesentlichen durch ein Ganzzahlfeld dargestellt, dessen Wert der Primärschlüssel des Fremdobjekts ist. Angenommen , Sie haben einen Eintrag comment_A , der einen Fremdschlüssel für einen Eintrag article_B enthält . Wenn Sie den Eintrag comment_A löschen , ist alles in Ordnung, article_B lebte früher ohne comment_A und kümmert sich nicht darum, ob er gelöscht wird. Wenn Sie jedoch article_B löschen , gerät comment_A in Panik! Es hat nie ohne article_B gelebt und braucht es, es ist Teil seiner Attribute (
article=article_B
aber was ist * article_B ** ???). Hier wirdon_delete
eingegriffen, um zu bestimmen, wie dieser Integritätsfehler behoben werden kannentweder mit den Worten:PROTECT
in SQL-Sprache gesagt wird)SET_NULL
)CASCADE
Verhalten).SET_DEFAULT
oder sogarSET(...)
).DO_NOTHING
)Ich hoffe, es macht die Kaskadenrichtung klarer. :) :)
quelle
Comment
ein Fremdschlüssel zumBlogPost
Löschen von BlogPost vorhanden ist, sollte der Kommentar gelöscht werden, aber das Löschen des Kommentars sollte BlogPost nicht löschen, unabhängig von RDMS?Comment
, wer das FK-Feld in seiner Tabelle hat, während erBlogPost
"besitzt",Comment
wenn wir über das reale Modell sprechen. Gut.Die
on_delete
Methode wird verwendet, um Django mitzuteilen, was mit Modellinstanzen zu tun ist, die von der zu löschenden Modellinstanz abhängen. (zB eineForeignKey
Beziehung). Dason_delete=models.CASCADE
weist Django an, den Löscheffekt zu kaskadieren, dh auch weiterhin die abhängigen Modelle zu löschen.Hier ist ein konkreteres Beispiel. Angenommen, Sie haben ein
Author
Modell, das sichForeignKey
in einemBook
Modell befindet. Wenn Sie nun eine Instanz desAuthor
Modells löschen , weiß Django nicht, was mit Instanzen desBook
Modells zu tun ist , die von dieser Instanz desAuthor
Modells abhängen . Dieon_delete
Methode teilt Django mit, was in diesem Fall zu tun ist. Durch die Einstellungon_delete=models.CASCADE
wird Django angewiesen, den Löscheffekt zu kaskadieren, dh alleBook
Modellinstanzen zu löschen , die von der vonAuthor
Ihnen gelöschten Modellinstanz abhängen .Hinweis:
on_delete
Wird in Django 2.0 zu einem erforderlichen Argument. In älteren Versionen wird standardmäßig verwendetCASCADE
.Hier ist die gesamte offizielle Dokumentation.
quelle
Zu Ihrer Information, der
on_delete
Parameter in Modellen ist rückwärts von dem, wie es sich anhört. Sie setzenon_delete
einen Fremdschlüssel (FK) für ein Modell ein, um Django mitzuteilen, was zu tun ist, wenn der FK-Eintrag, auf den Sie in Ihrem Datensatz zeigen, gelöscht wird. Die Optionen unserem Shop verwendet haben , die meisten sindPROTECT
,CASCADE
undSET_NULL
. Hier sind die Grundregeln, die ich herausgefunden habe:PROTECT
Sie diese Option, wenn Ihr FK auf eine Nachschlagetabelle zeigt, die sich wirklich nicht ändern sollte und die sicherlich nicht dazu führen sollte, dass sich Ihre Tabelle ändert. Wenn jemand versucht, einen Eintrag in dieser Nachschlagetabelle zu löschen, wirdPROTECT
verhindert , dass er ihn löscht, wenn er an einen Datensatz gebunden ist. Es verhindert auch, dass Django Ihren Datensatz löscht , nur weil ein Eintrag in einer Nachschlagetabelle gelöscht wurde. Dieser letzte Teil ist kritisch. Wenn jemand das Geschlecht "weiblich" aus meiner Geschlechtstabelle löschen würde, würde ich BESTIMMT NICHT wollen, dass dadurch sofort alle Personen gelöscht werden, die ich in meiner Personentabelle hatte und die dieses Geschlecht hatten.CASCADE
Sie diese Option, wenn Ihre FK auf einen "übergeordneten" Datensatz zeigt. Also, wenn eine Person viele PersonEthnicity Einträge haben kann (kann er / sie indianischer, Schwarz und Weiß sein), und diese Person wird gelöscht, ich wirklich würde wollen alle „Kind“ PersonEthnicity Einträge gelöscht werden. Sie sind ohne die Person irrelevant.SET_NULL
Sie diese Option, wenn Sie möchten, dass Personen einen Eintrag in einer Nachschlagetabelle löschen dürfen, Ihre Aufzeichnung jedoch beibehalten werden soll. Wenn zum Beispiel eine Person eine HighSchool haben kann, es mir aber nicht wirklich wichtig ist, ob diese High School auf meinem Nachschlagetisch verschwindet, würde ich sagenon_delete=SET_NULL
. Dies würde meine Person Aufzeichnung dort draußen lassen; es würde nur die High-School-FK auf meiner Person auf null setzen. Natürlich müssen Sienull=True
diese FK zulassen .Hier ist ein Beispiel eines Modells, das alle drei Dinge tut:
Wussten Sie als letzten Leckerbissen, dass das Standardverhalten lautet , wenn Sie nichts angeben
on_delete
(oder nicht angeben )CASCADE
? Dies bedeutet, dass, wenn jemand einen Geschlechtseintrag in Ihrer Gender-Tabelle gelöscht hat, auch alle Personendatensätze mit diesem Geschlecht gelöscht wurden!Ich würde sagen: "Wenn Sie Zweifel haben, setzen Sie
on_delete=models.PROTECT
." Dann testen Sie Ihre Anwendung. Sie werden schnell herausfinden, welche FKs mit den anderen Werten gekennzeichnet werden sollten, ohne Ihre Daten zu gefährden.Es ist auch erwähnenswert, dass
on_delete=CASCADE
keine Ihrer Migrationen tatsächlich hinzugefügt wird, wenn dies das von Ihnen ausgewählte Verhalten ist. Ich denke, das liegt daran, dass es die Standardeinstellung ist. Puttenon_delete=CASCADE
ist also dasselbe wie Putten nichts.quelle
Wie bereits erwähnt, löscht CASCADE den Datensatz mit einem Fremdschlüssel und verweist auf ein anderes Objekt, das gelöscht wurde. Zum Beispiel, wenn Sie eine Immobilienwebsite und eine Immobilie haben, die auf eine Stadt verweist
und jetzt, wenn die Stadt aus der Datenbank gelöscht wird, werden auch alle zugehörigen Immobilien (z. B. Immobilien in dieser Stadt) aus der Datenbank gelöscht
Jetzt möchte ich auch die Vorzüge anderer Optionen erwähnen, wie SET_NULL oder SET_DEFAULT oder sogar DO_NOTHING. Grundsätzlich möchten Sie aus Verwaltungssicht diese Datensätze "löschen". Aber du willst nicht wirklich, dass sie verschwinden. Aus vielen Gründen. Jemand hat es möglicherweise versehentlich gelöscht oder zur Prüfung und Überwachung. Und einfache Berichterstattung. So kann es eine Möglichkeit sein, das Eigentum von einer Stadt zu "trennen". Auch hier kommt es darauf an, wie Ihre Bewerbung geschrieben ist.
Beispielsweise haben einige Anwendungen ein Feld "gelöscht", das 0 oder 1 ist. Alle Suchanfragen und Listenansichten usw., alles, was in Berichten oder überall dort angezeigt werden kann, wo der Benutzer vom Front-End aus darauf zugreifen kann, schließen alles aus, was ist
deleted == 1
. Wenn Sie jedoch einen benutzerdefinierten Bericht oder eine benutzerdefinierte Abfrage erstellen, um eine Liste der gelöschten Datensätze abzurufen, und noch mehr, um zu sehen, wann sie zuletzt geändert wurden (ein anderes Feld) und von wem (dh wer sie wann gelöscht hat). das ist aus exekutiver Sicht sehr vorteilhaft.Und vergessen Sie nicht, dass Sie versehentliche Löschvorgänge so einfach wie
deleted = 0
bei diesen Datensätzen rückgängig machen können.Mein Punkt ist, wenn es eine Funktionalität gibt, gibt es immer einen Grund dahinter. Nicht immer ein guter Grund. Aber ein Grund. Und oft auch eine gute.
quelle
Hier ist die Antwort auf Ihre Frage: Warum verwenden wir on_delete?
Wenn ein Objekt, auf das von einem ForeignKey verwiesen wird, gelöscht wird, emuliert Django standardmäßig das Verhalten der SQL-Einschränkung ON DELETE CASCADE und löscht auch das Objekt, das den ForeignKey enthält. Dieses Verhalten kann durch Angabe des Arguments on_delete überschrieben werden. Wenn Sie beispielsweise einen nullbaren ForeignKey haben und möchten, dass dieser beim Löschen des referenzierten Objekts auf null gesetzt wird:
Die möglichen Werte für on_delete finden Sie in django.db.models:
CASCADE: Kaskade wird gelöscht; der Standard.
PROTECT: Verhindern Sie das Löschen des referenzierten Objekts, indem Sie ProtectedError, eine Unterklasse von django.db.IntegrityError, auslösen.
SET_NULL: Setzen Sie den ForeignKey auf null. Dies ist nur möglich, wenn null True ist.
SET_DEFAULT: Setzen Sie den ForeignKey auf seinen Standardwert. Für den ForeignKey muss ein Standard festgelegt werden.
quelle
Angenommen, Sie haben zwei Modelle, eines mit dem Namen Person und eines mit dem Namen Companies .
Per Definition kann eine Person mehr als ein Unternehmen gründen.
Da ein Unternehmen nur eine Person haben kann, möchten wir, dass beim Löschen einer Person alle mit dieser Person verbundenen Unternehmen ebenfalls gelöscht werden.
Wir beginnen also damit, ein Personenmodell wie dieses zu erstellen
Dann kann das Unternehmensmodell so aussehen
Beachten Sie die Verwendung
on_delete=models.CASCADE
in den Modellfirmen. Das heißt, alle Unternehmen zu löschen, wenn die Person, der es gehört (Instanz der Klasse Person), gelöscht wird.quelle
Richten Sie Ihr mentales Modell der Funktionalität von "CASCADE" neu aus, indem Sie daran denken, einer bereits vorhandenen Kaskade (dh einem Wasserfall) eine FK hinzuzufügen. Die Quelle dieses Wasserfalls ist ein Primärschlüssel. Löscht den Fluss nach unten.
Wenn Sie also on_delete eines FK als "CASCADE" definieren, fügen Sie den Datensatz dieses FK zu einer Kaskade von Löschvorgängen hinzu, die von der PK stammen. Der FK-Datensatz kann an dieser Kaskade teilnehmen oder nicht ("SET_NULL"). In der Tat kann ein Datensatz mit einem FK sogar den Fluss der Löschvorgänge verhindern! Baue einen Damm mit "PROTECT".
quelle
Die Verwendung von CASCADE bedeutet, Django tatsächlich anzuweisen, den referenzierten Datensatz zu löschen. Im folgenden Beispiel für eine Umfrage-App: Wenn eine 'Frage' gelöscht wird, werden auch die Auswahlmöglichkeiten dieser Frage gelöscht.
zB Frage: Wie haben Sie von uns erfahren? (Auswahlmöglichkeiten: 1. Freunde 2. Fernsehwerbung 3. Suchmaschine 4. E-Mail-Werbung)
Wenn Sie diese Frage löschen, werden auch alle diese vier Auswahlmöglichkeiten aus der Tabelle gelöscht. Beachten Sie, in welche Richtung es fließt. Sie müssen on_delete = models.CASCADE nicht in Frage stellen. Model hat es in die Auswahl aufgenommen.
quelle