Para su información, el on_delete
parámetro en los modelos es al revés de lo que parece. Pones on_delete
una clave externa (FK) en un modelo para decirle a django qué hacer si se elimina la entrada FK a la que estás apuntando en tu registro. La opciones de nuestra tienda han utilizado la mayoría son PROTECT
, CASCADE
y SET_NULL
. Aquí están las reglas básicas que he descubierto:
- Úselo
PROTECT
cuando su FK esté apuntando a una tabla de búsqueda que realmente no debería estar cambiando y que ciertamente no debería causar que su tabla cambie. Si alguien intenta eliminar una entrada en esa tabla de búsqueda, PROTECT
evita que la elimine si está vinculada a algún registro. También evita que django elimine su registro solo porque eliminó una entrada en una tabla de búsqueda. Esta última parte es crítica. Si alguien eliminara el género "Femenino" de mi tabla de Género, CIERTAMENTE NO querría que eso elimine instantáneamente a todas las personas que tenía en mi tabla de Persona que tenían ese género.
- Úselo
CASCADE
cuando su FK esté apuntando a un registro "padre". Por lo tanto, si una persona puede tener muchas entradas PersonEthnicity (él / ella puede ser indio americano, negro y blanco), y esa persona se elimina, realmente me gustaría que se eliminen las entradas "child" PersonEthnicity. Son irrelevantes sin la Persona.
- Utilizar
SET_NULL
cuando no quiere que la gente se les permitirá borrar una entrada en una tabla de consulta, pero aún desea conservar su registro. Por ejemplo, si una persona puede tener una escuela secundaria, pero realmente no me importa si esa escuela secundaria desaparece en mi mesa de consulta, diría on_delete=SET_NULL
. Esto dejaría mi registro de Persona ahí afuera; solo establecería el FK de la escuela secundaria en mi Persona como nulo. Obviamente, tendrás que permitir null=True
ese FK.
Aquí hay un ejemplo de un modelo que hace las tres cosas:
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'
Como último dato, ¿sabía que si no especifica on_delete
(o no lo hizo), el comportamiento predeterminado es CASCADE
? Esto significa que si alguien eliminó una entrada de género en su tabla de Género, ¡cualquier registro de Persona con ese género también se eliminará!
Yo diría: "En caso de duda, listo on_delete=models.PROTECT
". Luego prueba tu aplicación. Rápidamente descubrirá qué FK deben etiquetarse como otros valores sin poner en peligro ninguno de sus datos.
Además, vale la pena señalar que en on_delete=CASCADE
realidad no se agrega a ninguna de sus migraciones, si ese es el comportamiento que está seleccionando. Supongo que esto se debe a que es el valor predeterminado, por lo que poner on_delete=CASCADE
es lo mismo que no poner nada.