Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Django do cascading deletes on foreign keys?

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?

like image 499
mallyvai Avatar asked Sep 26 '15 04:09

mallyvai


People also ask

What is the use of on delete cascade in Django?

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.

How does foreign key on delete cascade work?

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.

What is the purpose on delete cascade deletes the?

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.


2 Answers

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.

like image 96
Paulo Pessoa Avatar answered Sep 29 '22 12:09

Paulo Pessoa


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.

like image 41
solarissmoke Avatar answered Sep 29 '22 11:09

solarissmoke