Estou familiarizado com o Django, mas recentemente notei que existe uma on_delete=models.CASCADE
opção com os modelos. Procurei a documentação para o mesmo, mas não consegui encontrar nada além de:
Alterado no Django 1.9:
on_delete
agora pode ser usado como o segundo argumento posicional (anteriormente, normalmente era passado apenas como argumento de palavra-chave). Será um argumento necessário no Django 2.0.
from django.db import models
class Car(models.Model):
manufacturer = models.ForeignKey(
'Manufacturer',
on_delete=models.CASCADE,
)
# ...
class Manufacturer(models.Model):
# ...
pass
O que on_delete faz? ( Eu acho que as ações a serem executadas se o modelo for excluído )
O que models.CASCADE
faz? ( alguma dica na documentação )
Que outras opções estão disponíveis ( se meu palpite estiver correto )?
Onde reside a documentação para isso?
python
django
django-models
Tudo é muito
fonte
fonte
Respostas:
Esse é o comportamento a ser adotado quando o objeto referenciado é excluído. Não é específico para o django, este é um padrão SQL.
Existem 6 ações possíveis a serem executadas quando esse evento ocorrer:
CASCADE
: Quando o objeto referenciado for excluído, exclua também os objetos que têm referências a ele (quando você remove uma postagem de blog, por exemplo, também pode excluir comentários). SQL equivalentes:CASCADE
.PROTECT
: Proíbe a exclusão do objeto referenciado. Para excluí-lo, você terá que excluir todos os objetos que fazem referência manualmente. SQL equivalentes:RESTRICT
.SET_NULL
: Defina a referência como NULL (requer que o campo seja anulável). Por exemplo, ao excluir um usuário, você pode manter os comentários que ele postou nas postagens do blog, mas dizer que foram postados por um usuário anônimo (ou excluído). SQL equivalentes:SET NULL
.SET_DEFAULT
: Defina o valor padrão. SQL equivalentes:SET DEFAULT
.SET(...)
: Defina um determinado valor. Este não faz parte do padrão SQL e é inteiramente tratado pelo Django.DO_NOTHING
: Provavelmente, é uma péssima idéia, pois isso criaria problemas de integridade no banco de dados (referenciando um objeto que realmente não existe). SQL equivalentes:NO ACTION
.Fonte: documentação do Django
Veja também a documentação do PostGreSQL, por exemplo.
Na maioria dos casos,
CASCADE
é o comportamento esperado, mas para cada ForeignKey, você deve sempre se perguntar qual é o comportamento esperado nessa situação.PROTECT
eSET_NULL
são frequentemente úteis. DefinirCASCADE
onde não deveria, pode potencialmente excluir todo o seu banco de dados em cascata, simplesmente excluindo um único usuário.Nota adicional para esclarecer a direção da cascata
É engraçado notar que a direção da
CASCADE
ação não é clara para muitas pessoas. Na verdade, é engraçado notar que apenas aCASCADE
ação não é clara. Entendo que o comportamento em cascata pode ser confuso, no entanto, você deve pensar que é a mesma direção que qualquer outra ação . Assim, se você sente que aCASCADE
direção não está clara para você, na verdade significa que oon_delete
comportamento não está claro para você.No seu banco de dados, uma chave estrangeira é basicamente representada por um campo inteiro cujo valor é a chave primária do objeto externo. Digamos que você tenha uma entrada comment_A , que possui uma chave estrangeira para uma entrada article_B . Se você excluir a entrada comment_A , tudo está bem, o article_B costumava viver sem comment_A e não se incomodava em ser excluído. No entanto, se você excluir article_B , comment_A entra em pânico! Ele nunca viveu sem article_B e precisa, faz parte de seus atributos (
article=article_B
, mas o que é * article_B ** ???). É aqui que ason_delete
etapas para determinar como resolver esse erro de integridade, dizendo:PROTECT
na linguagem SQL)SET_NULL
)CASCADE
comportamento).SET_DEFAULT
, ou atéSET(...)
).DO_NOTHING
)Espero que isso torne a direção da cascata mais clara. :)
fonte
Comment
houver uma chave estrangeira paraBlogPost
excluir o BlogPost, você deve excluir o comentário, mas a exclusão do comentário não deve excluir o BlogPost, independentemente do RDMS?Comment
quem tem o campo FK em sua tabela, enquantoBlogPost
"possui"Comment
s se falamos sobre o modelo da vida real. Boa.O
on_delete
método é usado para dizer ao Django o que fazer com instâncias de modelo que dependem da instância de modelo que você excluiu. (por exemplo, umForeignKey
relacionamento). Oon_delete=models.CASCADE
comando diz ao Django para colocar em cascata o efeito de exclusão, ou seja, continue excluindo os modelos dependentes também.Aqui está um exemplo mais concreto. Suponha que você tenha um
Author
modelo que é umForeignKey
em umBook
modelo. Agora, se você excluir uma instância doAuthor
modelo, o Django não saberá o que fazer com instâncias doBook
modelo que dependem dessa instância doAuthor
modelo. Oon_delete
método diz ao Django o que fazer nesse caso. A configuraçãoon_delete=models.CASCADE
instruirá o Django a aplicar em cascata o efeito de exclusão, ou seja, excluir todas asBook
instâncias do modelo que dependem daAuthor
instância que você excluiu.Nota:
on_delete
se tornará um argumento obrigatório no Django 2.0. Nas versões mais antigas, o padrão éCASCADE
.Aqui está toda a documentação oficial.
fonte
Para sua informação, o
on_delete
parâmetro nos modelos é inverso ao que parece. Você colocaon_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ãoPROTECT
,CASCADE
eSET_NULL
. Aqui estão as regras básicas que eu descobri: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.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.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 diriaon_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 permitirnull=True
esse FK.Aqui está um exemplo de um modelo que faz todas as três coisas:
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 colocaron_delete=CASCADE
é a mesma coisa que colocar nada.fonte
Como mencionado anteriormente, o CASCADE excluirá o registro que possui uma chave estrangeira e fará referência a outro objeto que foi excluído. Por exemplo, se você tem um site imobiliário e uma propriedade que faz referência a uma cidade
e agora, quando a cidade for excluída do banco de dados, todas as propriedades associadas (por exemplo, imóveis localizados nessa cidade) também serão excluídas do banco de dados
Agora também quero mencionar o mérito de outras opções, como SET_NULL ou SET_DEFAULT ou até DO_NOTHING. Basicamente, da perspectiva da administração, você deseja "excluir" esses registros. Mas você realmente não quer que eles desapareçam. Por muitas razões. Alguém pode ter excluído o arquivo acidentalmente ou para auditoria e monitoramento. E relatórios simples. Portanto, pode ser uma maneira de "desconectar" a propriedade de uma cidade. Novamente, isso dependerá de como o seu aplicativo for gravado.
Por exemplo, alguns aplicativos têm um campo "excluído" que é 0 ou 1. E todas as suas pesquisas e exibições de lista, etc., qualquer coisa que possa aparecer nos relatórios ou em qualquer lugar em que o usuário possa acessá-lo pelo front end, exclui qualquer coisa que esteja
deleted == 1
. No entanto, se você criar um relatório personalizado ou uma consulta personalizada para exibir uma lista de registros que foram excluídos e ainda mais para ver quando foi modificado pela última vez (outro campo) e por quem (por exemplo, quem o excluiu e quando). isso é muito vantajoso do ponto de vista executivo.E não esqueça que você pode reverter exclusões acidentais tão simples quanto
deleted = 0
para esses registros.Meu argumento é que, se houver uma funcionalidade, sempre haverá uma razão por trás disso. Nem sempre é uma boa razão. Mas uma razão. E muitas vezes uma boa também.
fonte
Aqui está a resposta para sua pergunta que diz: por que usamos on_delete?
Quando um objeto referenciado por uma ForeignKey é excluído, o Django, por padrão, emula o comportamento da restrição SQL ON DELETE CASCADE e também exclui o objeto que contém a ForeignKey. Esse comportamento pode ser substituído, especificando o argumento on_delete. Por exemplo, se você tiver uma ForeignKey anulável e desejar que ela seja definida como nula quando o objeto referenciado for excluído:
Os valores possíveis para on_delete são encontrados em django.db.models:
CASCADE: exclusões em cascata; o padrão.
PROTECT: Impeça a exclusão do objeto referenciado aumentando ProtectedError, uma subclasse de django.db.IntegrityError.
SET_NULL: define o ForeignKey nulo; isso só é possível se nulo for True.
SET_DEFAULT: Defina a ForeignKey como seu valor padrão; um padrão para a ForeignKey deve ser definido.
fonte
Digamos que você tenha dois modelos, um chamado Pessoa e outro chamado Empresas .
Por definição, uma pessoa pode criar mais de uma empresa.
Considerando que uma empresa pode ter uma e apenas uma pessoa, queremos que, quando uma pessoa for excluída, todas as empresas associadas a ela também sejam excluídas.
Então, começamos criando um modelo Person, como este
Então, o modelo de empresas pode ficar assim
Observe o uso das
on_delete=models.CASCADE
empresas modelo. Isso é para excluir todas as empresas quando a pessoa que possui (instância da classe Person) é excluída.fonte
Reoriente seu modelo mental da funcionalidade de "CASCADE" pensando em adicionar um FK a uma cascata já existente (ou seja, uma cascata). A fonte dessa cascata é uma chave primária. Exclui o fluxo para baixo.
Portanto, se você definir o on_delete de um FK como "CASCADE", estará adicionando o registro desse FK a uma cascata de exclusões originárias do PK. O registro do FK pode participar dessa cascata ou não ("SET_NULL"). De fato, um registro com um FK pode até impedir o fluxo das exclusões! Construa uma barragem com "PROTEGER".
fonte
Usar CASCADE significa dizer ao Django para excluir o registro referenciado. No exemplo do aplicativo de pesquisa abaixo: Quando uma 'Pergunta' é excluída, ela também exclui as Opções que esta Pergunta possui.
eg Pergunta: Como você ficou sabendo sobre nós? (Opções: 1. Amigos 2. Anúncio na TV 3. Mecanismo de pesquisa 4. Promoção por e-mail)
Quando você exclui esta pergunta, ela também exclui todas essas quatro opções da tabela. Observe a direção em que ele flui. Você não precisa colocar on_delete = models.CASCADE no modelo de perguntas, colocá-lo na opção.
fonte