Naveera A.
—What does the on_delete
option do in Django models?
The on_delete
option determines how the deletion of referenced data will be handled by the database to maintain data integrity.
Let’s say we are making a learning management system (LMS). We define the following models:
class Student(models.Model): name = models.CharField(max_length = 255) class Homework(models.Model): title = models.CharField(max_length = 255) student = models.ForeignKey(Student, on_delete=models.CASCADE)
The Homework
model stores a reference to the student who submitted that homework as a ForeignKey
. A ForeignKey
is a many-to-one relationship, which means that every student can submit multiple homework assignments, but each homework assignment can be submitted by only one student.
Let’s create an instance of both objects:
# Run these commands in Django shell student = Student.objects.create(name="Jane") homework = Homework.objects.create(title="Jane's homework", student=student_1)
What happens if we want to delete homework
? We can do so without any problem as student
doesn’t contain any reference to homework
. The student
instance existed before we created homework
and it can carry on existing after we delete homework
.
But before we can delete student
, we have to tell Django what to do with homework
. Do we want orphaned homework
instances lying around in our LMS? Or do we need to delete all the homework
submitted by a student when that student is deleted?
This is where the on_delete
option is used. It tells Django what behavior to adopt when the referenced object is deleted. We can set on_delete
to one of seven options. Let’s take a look at each option:
Cascades deletes. When we delete student
, homework
will also be deleted.
# models.py class Homework(models.Model): ... student = models.ForeignKey(Student, on_delete=models.CASCADE) # Django shell student.delete() # also deletes homework
Prevents deletion of the referenced object. When we try to delete student
, we will get a ProtectedError:
# models.py class Homework(models.Model): ... student = models.ForeignKey(Student, on_delete=models.PROTECT) # Django shell student.delete() # Raises ProtectedError. We first need to delete homework before Django will allow us to delete student.
Prevents deletion of the referenced object. When we try to delete student
, we will get a RestrictedError:
# models.py class Homework(models.Model): ... student = models.ForeignKey(Student, on_delete=models.RESTRICT) # Django shell student.delete() # Raises RestrictedError.
Unlike PREVENT
, RESTRICT
allows deletion of a referenced object if it also references a different object that is being deleted in the same operation, but via a CASCADE
relationship. To learn more, see the example in Django documentation.
This option sets the ForeignKey
to null
, but we have to specify null=True
in our model.
# models.py class Homework(models.Model): ... student = models.ForeignKey(Student, on_delete=models.SET_NULL, null=True) # Django shell student.delete() # Sets the foreign key in homework to null and deletes student.
This option sets the ForeignKey
to its default value, but we have to specify a default value in our model.
# models.py class Homework(models.Model): ... student = models.ForeignKey(Student, on_delete=models.SET_DEFAULT, default=1) # Django shell student.delete() # Sets the foreign key in homework to the student whose id is 1, and deletes student.
This option sets the ForeignKey
to the value passed to SET()
# models.py class Homework(models.Model): ... student = models.ForeignKey(Student, on_delete=models.SET(get_student)) # Django shell student.delete() # Calls the get_student function that you have defined, sets the foreign key in homework to the value returned by the get_student function, and deletes student.
This option makes no changes to the object with the ForeignKey
. In most cases, DO_NOTHING
is a bad choice as it can create integrity issues. But some advance level use cases might need this option.
# models.py class Homework(models.Model): ... student = models.ForeignKey(Student, on_delete=models.DO_NOTHING) # Django shell student.delete() # Deletes student. Makes no changes to homework.
Tasty treats for web developers brought to you by Sentry. Get tips and tricks from Wes Bos and Scott Tolinski.
SEE EPISODESConsidered “not bad” by 4 million developers and more than 100,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.
Here’s a quick look at how Sentry handles your personal information (PII).
×We collect PII about people browsing our website, users of the Sentry service, prospective customers, and people who otherwise interact with us.
What if my PII is included in data sent to Sentry by a Sentry customer (e.g., someone using Sentry to monitor their app)? In this case you have to contact the Sentry customer (e.g., the maker of the app). We do not control the data that is sent to us through the Sentry service for the purposes of application monitoring.
Am I included?We may disclose your PII to the following type of recipients:
You may have the following rights related to your PII:
If you have any questions or concerns about your privacy at Sentry, please email us at compliance@sentry.io.
If you are a California resident, see our Supplemental notice.