Cordiali saluti, il on_delete
parametro nei modelli è all'indietro da quello che sembra. Metti on_delete
una chiave esterna (FK) su un modello per dire a django cosa fare se la voce FK che stai indicando sul tuo record viene eliminata. Le opzioni nostro negozio hanno usato la maggior parte sono PROTECT
, CASCADE
e SET_NULL
. Ecco le regole di base che ho capito:
- Utilizzare
PROTECT
quando l'FK punta a una tabella di ricerca che in realtà non dovrebbe cambiare e che certamente non dovrebbe far cambiare la tabella. Se qualcuno tenta di eliminare una voce in quella tabella di ricerca, PROTECT
impedisce di eliminarla se è associata a qualsiasi record. Impedisce inoltre a django di eliminare il record solo perché ha eliminato una voce in una tabella di ricerca. Quest'ultima parte è fondamentale. Se qualcuno dovesse eliminare il genere "Femmina" dalla mia tabella Sesso, Certamente NON vorrei che eliminasse istantaneamente tutte le persone che avevo nella mia tabella Persona che avevano quel genere.
- Utilizzare
CASCADE
quando l'FK punta a un record "genitore". Quindi, se una persona può avere molte voci PersonEthnicity (lui / lei può essere americano indiano, nero e bianco), e quella persona è cancellato, ho davvero avrebbe voglia qualsiasi "bambino" PersonEthnicity voci da eliminare. Sono irrilevanti senza la Persona.
- Utilizzare
SET_NULL
quando non desidera la gente a essere consentito di eliminare una voce su un look-up table, ma si vuole ancora conservare il record. Ad esempio, se una persona può avere una scuola superiore, ma per me non importa se quella scuola va via sul mio tavolo di ricerca, direi on_delete=SET_NULL
. Questo lascerebbe il mio record personale là fuori; avrebbe semplicemente impostato l'FK del liceo sulla mia persona su null. Ovviamente, dovrai consentire null=True
su quell'FK.
Ecco un esempio di un modello che fa tutte e tre le cose:
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'
Come ultima notizia, sapevi che se non specifichi on_delete
(o non lo hai fatto), il comportamento predefinito è CASCADE
? Ciò significa che se qualcuno ha eliminato una voce di genere nella tua tabella Sesso, anche tutti i record di Persona con quel genere sono stati eliminati!
Direi "In caso di dubbi, imposta on_delete=models.PROTECT
". Quindi prova l'applicazione. Capirai rapidamente quali FK dovrebbero essere etichettati con gli altri valori senza mettere in pericolo i tuoi dati.
Inoltre, vale la pena notare che in on_delete=CASCADE
realtà non viene aggiunto a nessuna delle tue migrazioni, se questo è il comportamento che stai selezionando. Immagino che sia perché è l'impostazione predefinita, quindi mettere on_delete=CASCADE
è la stessa cosa di non mettere nulla.