I'm quite familiar with Django, but recently noticed there exists an on_delete=models.CASCADE
option with the models, I have searched for the documentation for the same but 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.
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?
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. aForeignKey
relationship). Theon_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 aForeignKey
in aBook
model. Now, if you delete an instance of theAuthor
model, Django would not know what to do with instances of theBook
model that depend on that instance ofAuthor
model. Theon_delete
method tells Django what to do in that case. Settingon_delete=models.CASCADE
will instruct Django to cascade the deleting effect i.e. delete all theBook
model instances that depend on theAuthor
model instance you deleted.Note:
on_delete
will become a required argument in Django 2.0. In older versions it defaults toCASCADE
.Here's the entire official documentation.
As mentioned earlier, CASCADE will delete the record that has a foreign key and references another object that was deleted. So for example if you have a real estate website and have a Property that references a City
and now when the City is deleted from the database, all associated Properties (eg. real estate located in that city) will also be deleted from the database
Now I also want to mention the merit of other options, such as SET_NULL or SET_DEFAULT or even DO_NOTHING. Basically, from the administration perspective, you want to "delete" those records. But you don't really want them to disappear. For many reasons. Someone might have deleted it accidentally, or for auditing and monitoring. And plain reporting. So it can be a way to "disconnect" the property from a City. Again, it will depend on how your application is written.
For example, some applications have a field "deleted" which is 0 or 1. And all their searches and list views etc, anything that can appear in reports or anywhere the user can access it from the front end, exclude anything that is
deleted == 1
. However, if you create a custom report or a custom query to pull down a list of records that were deleted and even more so to see when it was last modified (another field) and by whom (i.e. who deleted it and when)..that is very advantageous from the executive standpoint.And don't forget that you can revert accidental deletions as simple as
deleted = 0
for those records.My point is, if there is a functionality, there is always a reason behind it. Not always a good reason. But a reason. And often a good one too.
This is the behaviour to adopt when the referenced object is deleted. It is not specific to django, this is an SQL standard.
There are 6 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
.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
.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
andSET_NULL
are often useful. SettingCASCADE
where it should not, can potentially delete all your database in cascade, by simply deleting a single user.FYI, the on_delete parameter in models is backwards from what it sounds like. You put "on_delete" on a Foreign Key (FK) on a model to tell django what to do if the FK entry that you are pointing to on your record is deleted. The options our shop have used the most are PROTECT, CASCADE, and SET_NULL. Here are the basic rules I have figured out:
Here is an example of a model that does all three things:
As a last tidbit, did you know that if you don't specify on_delete (or didn't), the default behavior is CASCADE? This means that if someone deleted a gender entry on your Gender table, any Person records with that gender were also deleted!
I would say, "If in doubt, set on_delete=models.PROTECT." Then go test your application. You will quickly figure out which FKs should be labeled the other values without endangering any of your data.
Also, it is worth noting that on_delete=CASCADE is actually not added to any of your migrations, if that is the behavior you are selecting. I guess this is because it is the default, so putting on_delete=CASCADE is the same thing as putting nothing.
Here is answer for your question that says: why we use on_delete?
When an object referenced by a ForeignKey is deleted, Django by default emulates the behavior of the SQL constraint ON DELETE CASCADE and also deletes the object containing the ForeignKey. This behavior can be overridden by specifying the on_delete argument. For example, if you have a nullable ForeignKey and you want it to be set null when the referenced object is deleted:
The possible values for on_delete are found in django.db.models:
CASCADE: Cascade deletes; the default.
PROTECT: Prevent deletion of the referenced object by raising ProtectedError, a subclass of django.db.IntegrityError.
SET_NULL: Set the ForeignKey null; this is only possible if null is True.
SET_DEFAULT: Set the ForeignKey to its default value; a default for the ForeignKey must be set.