Para sua informação, o on_delete
parâmetro nos modelos é inverso ao que parece. Você coloca on_delete
uma chave estrangeira (FK) em um modelo para dizer ao django o que fazer se a entrada FK que você está apontando no seu registro for excluída. O opções de nossa loja têm usado a maioria são PROTECT
, CASCADE
e SET_NULL
. Aqui estão as regras básicas que eu descobri:
- Use
PROTECT
quando o seu FK estiver apontando para uma tabela de consulta que realmente não deveria estar mudando e que certamente não deve causar sua alteração. Se alguém tentar excluir uma entrada dessa tabela de pesquisa, PROTECT
impedirá que ela seja excluída se estiver vinculada a algum registro. Também evita que o django exclua seu registro apenas porque excluiu uma entrada em uma tabela de pesquisa. Esta última parte é crítica. Se alguém excluísse o gênero "Feminino" da minha tabela de Gênero, CERTAMENTE NÃO gostaria que isso excluísse instantaneamente toda e qualquer pessoa que eu tivesse na minha tabela Pessoa que tivesse esse gênero.
- Use
CASCADE
quando o seu FK estiver apontando para um registro "pai". Portanto, se uma pessoa puder ter muitas entradas PersonEthnicity (ele / ela pode ser índio americano, preto e branco) e essa pessoa for excluída, eu realmente gostaria que quaisquer entradas PersonEthnicity "filho" fossem excluídas. Eles são irrelevantes sem a Pessoa.
- Use
SET_NULL
quando você não quer que as pessoas para ser autorizado a excluir uma entrada em uma tabela look-up, mas você ainda quer preservar seu registro. Por exemplo, se uma pessoa pode ter uma escola secundária, mas realmente não importa para mim se essa escola desaparecer na minha mesa de pesquisa, eu diria on_delete=SET_NULL
. Isso deixaria meu registro pessoal lá fora; apenas definiria o FK do ensino médio na minha Pessoa como nulo. Obviamente, você terá que permitir null=True
esse FK.
Aqui está um exemplo de um modelo que faz todas as três coisas:
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 petisco, você sabia que, se não especificar on_delete
(ou não), o comportamento padrão é CASCADE
? Isso significa que se alguém excluiu uma entrada de gênero na sua tabela Gênero, qualquer registro de Pessoa com esse gênero também foi excluído!
Eu diria: "Em caso de dúvida, defina on_delete=models.PROTECT
". Em seguida, teste sua aplicação. Você descobrirá rapidamente quais FKs devem ser rotulados como outros valores sem pôr em risco nenhum dos seus dados.
Além disso, vale ressaltar que, on_delete=CASCADE
na verdade, não foi adicionado a nenhuma das suas migrações, se esse for o comportamento que você está selecionando. Eu acho que é porque é o padrão, então colocar on_delete=CASCADE
é a mesma coisa que colocar nada.