I'm quite familiar with Django, but I recently noticed there exists an on_delete=models.CASCADE
option with the models. I have searched for the documentation for the same, but I couldn't find anything more than:
Changed in Django 1.9:
on_delete
can now be used as the second positional argument (previously it was typically only passed as a keyword argument). It will be a required argument in Django 2.0.
An example case of usage is:
from django.db import models
class Car(models.Model):
manufacturer = models.ForeignKey(
'Manufacturer',
on_delete=models.CASCADE,
)
# ...
class Manufacturer(models.Model):
# ...
pass
What does on_delete do? (I guess the actions to be done if the model is deleted.)
What does models.CASCADE
do? (any hints in documentation)
What other options are available (if my guess is correct)?
Where does the documentation for this reside?
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.
The on_delete method is used to tell Django what to do with model instances that depend on the model instance you delete. (e.g. a ForeignKey relationship). The on_delete=models. CASCADE tells Django to cascade the deleting effect i.e. continue deleting the dependent models as well.
The __str__() method is called whenever you call str() on an object. Django uses str(obj) in a number of places. Most notably, to display an object in the Django admin site and as the value inserted into a template when it displays an object.
To define a relationship between two models, you need to define the ForeignKey field in the model from the Many side of the relationship. In other words, ForeignKey should be placed in the Child table, referencing the Parent table.
This is the behaviour to adopt when the referenced object is deleted. It is not specific to Django; this is an SQL standard. Although Django has its own implementation on top of SQL. (1)
There are seven possible actions to take when such event occurs:
CASCADE
: When the referenced object is deleted, also delete the objects that have references to it (when you remove a blog post for instance, you might want to delete comments as well). SQL equivalent: CASCADE
.PROTECT
: Forbid the deletion of the referenced object. To delete it you will have to delete all objects that reference it manually. SQL equivalent: RESTRICT
.RESTRICT
: (introduced in Django 3.1) Similar behavior as PROTECT
that matches SQL's RESTRICT
more accurately. (See django documentation example)SET_NULL
: Set the reference to NULL (requires the field to be nullable). For instance, when you delete a User, you might want to keep the comments he posted on blog posts, but say it was posted by an anonymous (or deleted) user. SQL equivalent: SET NULL
.SET_DEFAULT
: Set the default value. SQL equivalent: SET DEFAULT
.SET(...)
: Set a given value. This one is not part of the SQL standard and is entirely handled by Django.DO_NOTHING
: Probably a very bad idea since this would create integrity issues in your database (referencing an object that actually doesn't exist). SQL equivalent: NO ACTION
. (2)
Source: Django documentation
See also the documentation of PostgreSQL for instance.
In most cases, CASCADE
is the expected behaviour, but for every ForeignKey, you should always ask yourself what is the expected behaviour in this situation. PROTECT
and SET_NULL
are often useful. Setting CASCADE
where it should not, can potentially delete all of your database in cascade, by simply deleting a single user.
Additional note to clarify cascade direction
It's funny to notice that the direction of the CASCADE
action is not clear to many people. Actually, it's funny to notice that only the CASCADE
action is not clear. I understand the cascade behavior might be confusing, however you must think that it is the same direction as any other action. Thus, if you feel that CASCADE
direction is not clear to you, it actually means that on_delete
behavior is not clear to you.
In your database, a foreign key is basically represented by an integer field which value is the primary key of the foreign object. Let's say you have an entry comment_A, which has a foreign key to an entry article_B. If you delete the entry comment_A, everything is fine. article_B used to live without comment_A and don't bother if it's deleted. However, if you delete article_B, then comment_A panics! It never lived without article_B and needs it, and it's part of its attributes (article=article_B
, but what is article_B???). This is where on_delete
steps in, to determine how to resolve this integrity error, either by saying:
PROTECT
or RESTRICT
in Django/SQL)SET_NULL
)CASCADE
behavior).SET_DEFAULT
, or even SET(...)
).DO_NOTHING
)I hope it makes cascade direction clearer. :)
Footnotes
(1) Django has its own implementation on top of SQL. And, as mentioned by @JoeMjr2 in the comments below, Django will not create the SQL constraints. If you want the constraints to be ensured by your database (for instance, if your database is used by another application, or if you hang in the database console from time to time), you might want to set the related constraints manually yourself. There is an open ticket to add support for database-level on delete constrains in Django.
(2) Actually, there is one case where
DO_NOTHING
can be useful: If you want to skip Django's implementation and implement the constraint yourself at the database-level.
The on_delete
method is used to tell Django what to do with model instances that depend on the model instance you delete. (e.g. a ForeignKey
relationship). The on_delete=models.CASCADE
tells Django to cascade the deleting effect i.e. continue deleting the dependent models as well.
Here's a more concrete example. Assume you have an Author
model that is a ForeignKey
in a Book
model. Now, if you delete an instance of the Author
model, Django would not know what to do with instances of the Book
model that depend on that instance of Author
model. The on_delete
method tells Django what to do in that case. Setting on_delete=models.CASCADE
will instruct Django to cascade the deleting effect i.e. delete all the Book
model instances that depend on the Author
model instance you deleted.
Note: on_delete
will become a required argument in Django 2.0. In older versions it defaults to CASCADE
.
Here's the entire official documentation.
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