Je suis assez familier avec Django, mais récemment j'ai remarqué qu'il existe une on_delete=models.CASCADE
option avec les modèles, j'ai cherché la documentation pour le même mais je n'ai rien trouvé de plus que:
Modifié dans Django 1.9:
on_delete
peut désormais être utilisé comme deuxième argument positionnel (auparavant, il n'était généralement passé qu'en tant qu'argument de mot clé). Ce sera un argument obligatoire dans Django 2.0.
from django.db import models
class Car(models.Model):
manufacturer = models.ForeignKey(
'Manufacturer',
on_delete=models.CASCADE,
)
# ...
class Manufacturer(models.Model):
# ...
pass
Que fait on_delete? ( Je suppose que les actions à faire si le modèle est supprimé )
Que fait models.CASCADE
-il? ( toute indication dans la documentation )
Quelles autres options sont disponibles ( si ma supposition est correcte )?
Où se trouve la documentation pour cela?
python
django
django-models
Tout est possible
la source
la source
Réponses:
Il s'agit du comportement à adopter lorsque l' objet référencé est supprimé. Ce n'est pas spécifique à django, c'est un standard SQL.
Il y a 6 actions possibles à entreprendre lorsqu'un tel événement se produit:
CASCADE
: Lorsque l'objet référencé est supprimé, supprimez également les objets qui y font référence (lorsque vous supprimez un article de blog par exemple, vous pouvez également supprimer les commentaires). SQL équivalent:CASCADE
.PROTECT
: Interdit la suppression de l'objet référencé. Pour le supprimer, vous devrez supprimer tous les objets qui le référencent manuellement. SQL équivalent:RESTRICT
.SET_NULL
: Définissez la référence sur NULL (nécessite que le champ soit nullable). Par exemple, lorsque vous supprimez un utilisateur, vous souhaiterez peut-être conserver les commentaires qu'il a publiés sur les articles de blog, mais dire qu'il a été publié par un utilisateur anonyme (ou supprimé). SQL équivalent:SET NULL
.SET_DEFAULT
: Définissez la valeur par défaut. SQL équivalent:SET DEFAULT
.SET(...)
: Définissez une valeur donnée. Celui-ci ne fait pas partie du standard SQL et est entièrement géré par Django.DO_NOTHING
: Probablement une très mauvaise idée car cela créerait des problèmes d'intégrité dans votre base de données (référencer un objet qui n'existe pas réellement). SQL équivalent:NO ACTION
.Source: documentation Django
Voir aussi la documentation de PostGreSQL par exemple.
Dans la plupart des cas,
CASCADE
c'est le comportement attendu, mais pour chaque ForeignKey, vous devez toujours vous demander quel est le comportement attendu dans cette situation.PROTECT
etSET_NULL
sont souvent utiles. DéfinirCASCADE
où il ne devrait pas, peut potentiellement supprimer toute votre base de données en cascade, en supprimant simplement un seul utilisateur.Note supplémentaire pour clarifier la direction de la cascade
C'est drôle de remarquer que la direction de l'
CASCADE
action n'est pas claire pour beaucoup de gens. En fait, c'est drôle de remarquer que seule l'CASCADE
action n'est pas claire. Je comprends que le comportement en cascade peut être déroutant, mais vous devez penser que c'est la même direction que toute autre action . Ainsi, si vous sentez que laCASCADE
direction n'est pas claire pour vous, cela signifie en fait que leon_delete
comportement n'est pas clair pour vous.Dans votre base de données, une clé étrangère est essentiellement représentée par un champ entier dont la valeur est la clé primaire de l'objet étranger. Disons que vous avez une entrée comment_A , qui a une clé étrangère pour une entrée article_B . Si vous supprimez l'entrée comment_A , tout va bien, article_B utilisé pour vivre sans comment_A et ne dérange pas si elle est supprimée. Cependant, si vous supprimez article_B , alors comment_A panique! Il n'a jamais vécu sans article_B et en a besoin, cela fait partie de ses attributs (
article=article_B
, mais qu'est-ce que * article_B ** ???). C'est làon_delete
qu'intervient pour déterminer comment résoudre cette erreur d'intégrité, soit en disant:PROTECT
en langage SQL)SET_NULL
)CASCADE
comportement).SET_DEFAULT
, ou mêmeSET(...)
).DO_NOTHING
)J'espère que cela rend la direction de la cascade plus claire. :)
la source
Comment
a une clé étrangère pourBlogPost
supprimer ensuite BlogPost devrait supprimer le commentaire, mais la suppression du commentaire ne devrait pas supprimer BlogPost, indépendamment du SGBD?Comment
qui a le champ FK dans sa table, tandis queBlogPost
"possède"Comment
s si nous parlons du modèle de la vie réelle. Bien.La
on_delete
méthode est utilisée pour indiquer à Django quoi faire avec les instances de modèle qui dépendent de l'instance de modèle que vous supprimez. (par exemple uneForeignKey
relation). Leon_delete=models.CASCADE
dit à Django de répercuter l'effet de suppression, c'est-à-dire de continuer à supprimer également les modèles dépendants.Voici un exemple plus concret. Supposons que vous ayez un
Author
modèle qui estForeignKey
dans unBook
modèle. Maintenant, si vous supprimez une instance duAuthor
modèle, Django ne saurait pas quoi faire avec les instances duBook
modèle qui dépendent de cette instance deAuthor
modèle. Laon_delete
méthode indique à Django quoi faire dans ce cas. Le paramètreon_delete=models.CASCADE
demandera à Django de répercuter l'effet de suppression, c'est-à-dire de supprimer toutes lesBook
instances de modèle qui dépendent de l'Author
instance de modèle que vous avez supprimée.Remarque:
on_delete
deviendra un argument obligatoire dans Django 2.0. Dans les anciennes versions, il est par défautCASCADE
.Voici toute la documentation officielle.
la source
Pour info, le
on_delete
paramètre dans les modèles est à l'envers de ce à quoi il ressemble. Vous mettezon_delete
une clé étrangère (FK) sur un modèle pour dire à django quoi faire si l'entrée FK que vous pointez sur votre enregistrement est supprimée. Les options de notre boutique ont utilisé la plupart sontPROTECT
,CASCADE
etSET_NULL
. Voici les règles de base que j'ai découvert:PROTECT
lorsque votre FK pointe vers une table de recherche qui ne devrait vraiment pas changer et qui ne devrait certainement pas faire changer votre table. Si quelqu'un essaie de supprimer une entrée de cette table de recherche, lesPROTECT
empêche de la supprimer si elle est liée à des enregistrements. Cela empêche également django de supprimer votre enregistrement simplement parce qu'il a supprimé une entrée sur une table de recherche. Cette dernière partie est critique. Si quelqu'un supprimait le sexe "Femme" de ma table Sexe, je ne voudrais certainement pas que cela supprime instantanément toutes les personnes que j'avais dans ma table Personne qui avaient ce sexe.CASCADE
lorsque votre FK pointe vers un enregistrement "parent". Donc, si une personne peut avoir plusieurs entrées PersonEthnicity (il peut être un Indien de l'Amérique, un Noir et un Blanc) et que cette personne est supprimée, je voudrais vraiment que toutes les entrées PersonEthnicity "enfant" soient supprimées. Ils ne sont pas pertinents sans la personne.SET_NULL
lorsque vous ne voulez que les gens soient autorisés à supprimer une entrée sur une table de consultation, mais vous voulez toujours conserver votre dossier. Par exemple, si une personne peut avoir un lycée, mais cela n'a pas vraiment d'importance pour moi si ce lycée disparaît sur ma table de recherche, je diraison_delete=SET_NULL
. Cela laisserait mon dossier Personne là-bas; cela ne ferait que mettre le FK du secondaire sur ma personne à zéro. De toute évidence, vous devrez autorisernull=True
ce FK.Voici un exemple d'un modèle qui fait les trois choses:
Comme dernière friandise, saviez-vous que si vous ne le faites pas spécifiez
on_delete
(ou pas), le comportement par défaut estCASCADE
? Cela signifie que si quelqu'un a supprimé une entrée de sexe sur votre table de sexe, tous les enregistrements de personne avec ce sexe ont également été supprimés!Je dirais: "En cas de doute, partez
on_delete=models.PROTECT
". Allez ensuite tester votre application. Vous découvrirez rapidement quels FK doivent être étiquetés comme les autres valeurs sans mettre en danger vos données.En outre, il convient de noter que ce
on_delete=CASCADE
n'est en fait ajouté à aucune de vos migrations, si tel est le comportement que vous sélectionnez. Je suppose que c'est parce que c'est la valeur par défaut, donc mettreon_delete=CASCADE
est la même chose que ne rien mettre.la source
Comme mentionné précédemment, CASCADE supprimera l'enregistrement qui a une clé étrangère et fait référence à un autre objet qui a été supprimé. Ainsi, par exemple, si vous avez un site Web immobilier et avez une propriété qui fait référence à une ville
et maintenant, lorsque la ville est supprimée de la base de données, toutes les propriétés associées (par exemple, les biens immobiliers situés dans cette ville) seront également supprimées de la base de données
Maintenant, je veux également mentionner le mérite d'autres options, telles que SET_NULL ou SET_DEFAULT ou même DO_NOTHING. Fondamentalement, du point de vue de l'administration, vous souhaitez "supprimer" ces enregistrements. Mais vous ne voulez pas vraiment qu'ils disparaissent. Pour de nombreuses raisons. Il est possible que quelqu'un l'ait supprimé accidentellement, ou à des fins d'audit et de surveillance. Et des rapports clairs. Cela peut donc être un moyen de «déconnecter» la propriété d'une ville. Encore une fois, cela dépendra de la façon dont votre demande est écrite.
Par exemple, certaines applications ont un champ "supprimé" qui est 0 ou 1. Et toutes leurs recherches et vues de liste, etc., tout ce qui peut apparaître dans les rapports ou n'importe où l'utilisateur peut y accéder depuis le frontal, exclut tout ce qui est
deleted == 1
. Cependant, si vous créez un rapport personnalisé ou une requête personnalisée pour dérouler une liste d'enregistrements qui ont été supprimés et plus encore pour voir quand il a été modifié pour la dernière fois (un autre champ) et par qui (c'est-à-dire qui l'a supprimé et quand). c'est très avantageux du point de vue exécutif.Et n'oubliez pas que vous pouvez annuler les suppressions accidentelles aussi simple que
deleted = 0
pour ces enregistrements.Mon point est, s'il y a une fonctionnalité, il y a toujours une raison derrière elle. Pas toujours une bonne raison. Mais une raison. Et souvent bon aussi.
la source
Voici la réponse à votre question qui dit: pourquoi nous utilisons on_delete?
Lorsqu'un objet référencé par une ForeignKey est supprimé, Django émule par défaut le comportement de la contrainte SQL ON DELETE CASCADE et supprime également l'objet contenant la ForeignKey. Ce comportement peut être remplacé en spécifiant l'argument on_delete. Par exemple, si vous avez une ForeignKey nullable et que vous souhaitez qu'elle soit définie null lorsque l'objet référencé est supprimé:
Les valeurs possibles pour on_delete se trouvent dans django.db.models:
CASCADE: suppressions en cascade; le défaut.
PROTECT: empêche la suppression de l'objet référencé en augmentant ProtectedError, une sous-classe de django.db.IntegrityError.
SET_NULL: définissez la valeur ForeignKey null; cela n'est possible que si null est True.
SET_DEFAULT: définissez la clé étrangère sur sa valeur par défaut; une valeur par défaut pour ForeignKey doit être définie.
la source
Disons que vous avez deux modèles, un nommé Personne et un autre nommé Entreprises .
Par définition, une personne peut créer plus d'une entreprise.
Étant donné qu'une entreprise peut avoir une et une seule personne, nous voulons que lorsqu'une personne est supprimée, toutes les entreprises associées à cette personne soient également supprimées.
Donc, nous commençons par créer un modèle Personne, comme celui-ci
Ensuite, le modèle Entreprises peut ressembler à ceci
Remarquez l'utilisation de
on_delete=models.CASCADE
dans les sociétés modèles. Cela revient à supprimer toutes les sociétés lorsque la personne qui en est propriétaire (instance de la classe Personne) est supprimée.la source
Réorientez votre modèle mental de la fonctionnalité de "CASCADE" en pensant ajouter un FK à une cascade déjà existante (ie une cascade). La source de cette cascade est une clé primaire. Supprime le flux vers le bas.
Donc, si vous définissez on_delete d'un FK comme "CASCADE", vous ajoutez l'enregistrement de ce FK à une cascade de suppressions provenant du PK. L'enregistrement du FK peut participer ou non à cette cascade ("SET_NULL"). En fait, un enregistrement avec un FK peut même empêcher le flux des suppressions! Construisez un barrage avec "PROTECT".
la source
Utiliser CASCADE signifie en fait dire à Django de supprimer l'enregistrement référencé. Dans l'exemple de l'application de sondage ci-dessous: Lorsqu'une «question» est supprimée, elle supprime également les choix de cette question.
Ex. Question: Comment avez-vous entendu parler de nous? (Choix: 1. Amis 2. Publicité TV 3. Moteur de recherche 4. Promotion par e-mail)
Lorsque vous supprimez cette question, elle supprimera également ces quatre choix du tableau. Notez dans quelle direction il s'écoule. Vous n'avez pas à mettre on_delete = models.CASCADE dans Question Model le mettre dans le choix.
la source