2015-09-26 15 views
7

Django esegue un'eliminazione a cascata sui modelli con chiavi esterne come impostazione predefinita. Cioè, diciamo che hai una ForeignKey in A che punta a B, e cancelli B, quindi A verrà cancellato.Perché Django elimina le cascading sulle chiavi esterne?

This is known and documented, ma non ho trovato alcuna buona motivazione per la decisione di progettazione intorno a renderlo un valore predefinito, dato come sembra poco intuitivo. Qualcuno sa perché potrebbe essere il caso?

+0

Credo che sia perché un oggetto che dipende da altri non può esistere se la sua dipendenza non esiste. È una relazione tra requisiti per l'oggetto dipendente da esistere. Prendilo dal software, un programma non può funzionare se tutte le sue dipendenze non ci sono, giusto? –

+0

Perché vorresti mantenere un record correlato lì per impostazione predefinita? La maggior parte delle volte quando si elimina il record padre non è necessario per il bambino. –

risposta

10

7 anni fa ...

un biglietto è stato aperto #7539

dove ha cominciato ad essere discusso.

anni fa da benjaoming

Qualcuno ha richiesto una discussione ... Ho appena avuto un incontro con questo, e quello che mi mancava era sapendo quello che sta succedendo per quanto riguarda il cascata cancellazione, a causa è abbastanza pericoloso (perdi dati !!) e ruba un sacco di tempo. Prevenire è semplice, però. Sovrascrivere il metodo delete() di un modello e chiamare clear() sulle relative chiavi esterne del modello è semplice ed è un'implementazione manuale, che tutti i programmatori dovrebbero essere in grado di comprendere. Ma posso pensare a un'altra alternativa: Se null = True per la chiave esterna in questione, perché non usa automaticamente SET NULL quando l'istanza relativa viene cancellata? Per me, questo è ancora più "intuitivo" di CASCADE. Dopotutto, null = True è qualcosa che il programmatore specifica e deve occuparsi di con qualsiasi punto dell'implementazione, che è anche il motivo per cui non ha bisogno della cancellazione a cascata di tale relazione da parte di . Inoltre, se on_delete è possibile impostare in un campo chiave, dovrebbe rispettare l'opzione null .. e insieme con "argomento intuizione" che crea una corrispondenza 1: 1 tra le due opzioni. E poi il "ragionamento logico": Django gestisce la sua logica in codice Python, non nel Database, che è mantenuto come un semplice motore di archiviazione. L'opzione RESTRICT è un problema di convalida e probabilmente verrà gestito in questo modo nella maggior parte dei casi, pertanto disporre del database che lo impone sarà ridondante. Per abilitarlo sul livello di modello si potrebbe aprire la strada ad una nuova valida validazione automatica in ModelForms, quindi penso che possa sembrare una bella funzionalità. Se tutto questo è implementato, suggerirei di rimuovere l'opzione null dai campi chiave e impostarlo in base a on_delete.

anni più tardi, la questione è stata nuovamente discussa nel gruppo.

sviluppatori Django (Contributi a Django stesso)
changing the on_delete=CASCADE default

E poi altri biglietti sono stati creati#21127 e #21961.

E siamo arrivati ​​qui. ForeignKey and OneToOneField on_delete argument

Al fine di aumentare la consapevolezza circa cascata modello di eliminazione, il argomento on_delete di ForeignKey e OneToOneField sarà richiesto in Django 2.0.

Aggiornamento di modelli e migrazioni esistenti per impostare esplicitamente l'argomento. Poiché il valore predefinito è models.CASCADE, aggiungere on_delete = models.CASCADE a all ForeignKey e OneToOneFields che non utilizzano un'opzione diversa. Puoi anche passarlo come secondo argomento posizionale se non tieni conto di riguardo alla compatibilità con le versioni precedenti di Django.

+2

Grazie per tutto questo contesto! È bello sapere che ci sono alternative in programma, e felice di sentire che non sono il solo a pensare che sia sciocco ;-). Mi piace soprattutto l'idea di un argomento on_null impostato in modo esplicito. Qualche idea sulla giustificazione originale o è stata persa per i venti? – mallyvai

+0

hahau, penso che sia perso .. :) –

+1

Bello questo comportamento a cascata, ma sarebbe ancora più bello se fosse chiamato anche il metodo python delete degli oggetti figlio, invece di mettere solo un vincolo a cascata SQL sul DB ... Fortunatamente abbiamo segnali pre_delete e post_delete! Quindi suggerimento pro: non sovrascrivere il metodo di cancellazione su un modello, ma utilizzare i segnali! (peccato che non funzioni allo stesso modo con la creazione di massa e l'aggiornamento alla rinfusa ... ma questa è un'altra storia) – gabn88

Problemi correlati