Pour info, le on_delete
paramètre dans les modèles est à l'envers de ce à quoi il ressemble. Vous mettez on_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 sont PROTECT
, CASCADE
et SET_NULL
. Voici les règles de base que j'ai découvert:
- Utilisation
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, les PROTECT
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.
- À utiliser
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.
- Utilisez
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 dirais on_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 autoriser null=True
ce FK.
Voici un exemple d'un modèle qui fait les trois choses:
class PurchPurchaseAccount(models.Model):
id = models.AutoField(primary_key=True)
purchase = models.ForeignKey(PurchPurchase, null=True, db_column='purchase', blank=True, on_delete=models.CASCADE) # If "parent" rec gone, delete "child" rec!!!
paid_from_acct = models.ForeignKey(PurchPaidFromAcct, null=True, db_column='paid_from_acct', blank=True, on_delete=models.PROTECT) # Disallow lookup deletion & do not delete this rec.
_updated = models.DateTimeField()
_updatedby = models.ForeignKey(Person, null=True, db_column='_updatedby', blank=True, related_name='acctupdated_by', on_delete=models.SET_NULL) # Person records shouldn't be deleted, but if they are, preserve this PurchPurchaseAccount entry, and just set this person to null.
def __unicode__(self):
return str(self.paid_from_acct.display)
class Meta:
db_table = u'purch_purchase_account'
Comme dernière friandise, saviez-vous que si vous ne le faites pas spécifiezon_delete
(ou pas), le comportement par défaut est CASCADE
? 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 mettre on_delete=CASCADE
est la même chose que ne rien mettre.