Django does a cascading delete on models with foreign keys as a default. That is, say you have a ForeignKey in A pointing to B, and you delete B, then A will be deleted as well.
This is known and documented, but I haven't found any good rationale for the design decision around making it a default, given how unintuitive it seems. Does anyone know why it may be the case?
When we set the on_delete parameter as CASCADE, deleting the reference object will also delete the referred object. This option is most useful in many relationships.
A foreign key with cascade delete means that if a record in the parent table is deleted, then the corresponding records in the child table will automatically be deleted. This is called a cascade delete in SQL Server.
Use the ON DELETE CASCADE option to specify whether you want rows deleted in a child table when corresponding rows are deleted in the parent table. If you do not specify cascading deletes, the default behavior of the database server prevents you from deleting data in a table if other tables reference it.
7 Years ago...
a Ticket was open #7539
Where it began to be discussed.
years ago by benjaoming
Someone requested a discussion... I just had an encounter with this, and what I lacked was knowing what's going on with regards to cascading deletion, because it's quite dangerous (you loose data!!) and steals lots of time. Preventing it is simple, though. Overriding the delete() method of a model and calling clear() on the related model's foreign keys is simple, and it's a manual implementation, that all programmers should be able to understand. But I can think of another alternative: If null=True for the foreign key in question, why not automatically use SET NULL when the related instance is deleted? For me, this is even more "intuitive" than CASCADE. After all, null=True is something that the programmer specifies and has to deal with anywhere in the implementation, which is also why he doesn't need cascading deletion of such a relation. Also, if on_delete is possible to set in a key field, it would have to comply with the null option.. and together with the "intuition argument" that creates a 1:1 correspondence between the two options. And then the "logic argument": Django handles its logic in Python code, not in the Database, which is kept as a simple storage engine. The RESTRICT option is a validation issue, and will probably be handled this way in most cases, so having the database enforcing it, would be redundant. To enable it on model-level could pave the way for some nice new automatic validation in ModelForms, so I think it sounds like a nice feature. If all this is implemented, I would suggest to remove the null option from key fields and have it set according to on_delete.
Years later, the matter was again discussed in the group.
Django developers (Contributions to Django itself)
changing the on_delete=CASCADE default
And then other tickets were created #21127 and #21961.
And we got here. ForeignKey and OneToOneField on_delete argument
In order to increase awareness about cascading model deletion, the on_delete argument of ForeignKey and OneToOneField will be required in Django 2.0.
Update models and existing migrations to explicitly set the argument. Since the default is models.CASCADE, add on_delete=models.CASCADE to all ForeignKey and OneToOneFields that don’t use a different option. You can also pass it as the second positional argument if you don’t care about compatibility with older versions of Django.
There is a fairly lengthy discussion on this in this ticket. In Django 2.0 the on_delete
argument will be required so the current default behaviour will no longer apply.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With