Skip to main content

Python Django: How to Resolve "TypeError: init() missing 1 required positional argument: 'on_delete'"

When defining model relationships in Django, such as a ForeignKey or OneToOneField, you might encounter the TypeError: __init__() missing 1 required positional argument: 'on_delete'. This error is Django's way of telling you that you must explicitly define what should happen to an object when the object it refers to is deleted. This became a mandatory requirement in Django 2.0 to enforce clearer and safer database behavior.

This guide will explain why this argument is essential, show you how to fix the error, and provide a clear overview of the most common on_delete options so you can choose the right one for your model's logic.

Understanding the Error: Why on_delete is Required

This error is all about maintaining database integrity. Imagine a Pet model that has a relationship to a PetOwner model. If you delete a PetOwner from the database, what should happen to the Pet records that belong to them?

  • Should the pets be deleted too?
  • Should the pets be kept, but their owner field be set to NULL?
  • Should the deletion of the owner be blocked as long as they still have pets?

Instead of guessing, Django forces you to make this decision explicit by providing the on_delete argument. This prevents orphaned data and ensures your database remains in a consistent state.

Reproducing the TypeError

The error is triggered when you define a ForeignKey (or OneToOneField) without the on_delete parameter and then try to create migrations.

Example of code causing the error:

# myapp/models.py
from django.db import models

class PetOwner(models.Model):
name = models.CharField(max_length=200)
age = models.IntegerField(default=0)

class Pet(models.Model):
# ❌ Incorrect: The on_delete argument is missing from this ForeignKey.
owner = models.ForeignKey(PetOwner)
pet_name = models.CharField(max_length=200)

When you run makemigrations, Django analyzes this model and raises the TypeError.

python manage.py makemigrations

Output:

Traceback (most recent call last):
...
File "/path/to/your/project/myapp/models.py", line 11, in Pet
owner = models.ForeignKey(PetOwner)
TypeError: __init__() missing 1 required positional argument: 'on_delete'

The Solution: Adding the on_delete Argument

To fix this, you must add the on_delete argument to your ForeignKey field and specify the desired behavior. The most common option is models.CASCADE.

Solution:

# myapp/models.py
from django.db import models

class PetOwner(models.Model):
name = models.CharField(max_length=200)
age = models.IntegerField(default=0)

class Pet(models.Model):
# ✅ Correct: on_delete=models.CASCADE is now specified.
owner = models.ForeignKey(PetOwner, on_delete=models.CASCADE)
pet_name = models.CharField(max_length=200)

With this change, the makemigrations command will now succeed.

Common on_delete Options Explained

Choosing the right option is important for your application's logic. Here are the most common choices:

  • models.CASCADE

    • What it does: When the referenced object is deleted, Django also deletes the objects that have a reference to it. This "cascades" the deletion.
    • Example: If you delete a PetOwner, all of their associated Pet objects will also be deleted automatically. This is the most common behavior for parent-child relationships.
  • models.PROTECT

    • What it does: Prevents the deletion of the referenced object by raising a ProtectedError.
    • Example: If you try to delete a PetOwner that still has Pets linked to them, Django will block the deletion and raise an error. This is useful for preventing the accidental removal of objects that are still referenced elsewhere.
  • models.SET_NULL

    • What it does: Sets the ForeignKey field to NULL. This is only possible if the field is defined with null=True.
    • Example: If you delete a PetOwner, the owner field on their Pets will be set to NULL. The pet records themselves are not deleted.
      owner = models.ForeignKey(PetOwner, on_delete=models.SET_NULL, null=True)
  • models.SET_DEFAULT

    • What it does: Sets the ForeignKey to its default value. A default must be defined on the ForeignKey field for this to work.
    • Example: You could have a default "Shelter" PetOwner record, and when a specific owner is deleted, their pets are reassigned to the shelter.
warning

Avoid models.DO_NOTHING This option tells Django to do nothing at the application level. It passes the responsibility to the database. If your database does not have a corresponding constraint (like ON DELETE RESTRICT), this can lead to an IntegrityError and is generally not recommended unless you have a specific database-level strategy.

Conclusion

If you want to...Use this on_delete option
Delete dependent objects automaticallymodels.CASCADE
Prevent deletion if dependencies existmodels.PROTECT
Allow dependencies to become unlinkedmodels.SET_NULL (requires null=True)

The TypeError: __init__() missing 1 required positional argument: 'on_delete' is a deliberate design choice in modern Django to promote data integrity. By explicitly choosing an on_delete strategy for your model relationships, you create a more robust and predictable database schema.