Fixing Django IntegrityError: null value in column violates not-null constraint
While working on a Django project, I ran into an issue that resulted in this error:
django.db.utils.IntegrityError: null value in column "message_id" of relation "mailing_sending" violates not-null constraint
DETAIL: Failing row contains (..., null, null, ...).
This happened while calling delete()
on a model instance. Django was trying to set a foreign key field to NULL
as part of a cascading delete, but the database rejected it due to a NOT NULL
constraint.
Root Cause
In our Django model, we had defined a nullable foreign key:
message = models.ForeignKey(Message, on_delete=models.SET_NULL, null=True)
However, in the PostgreSQL database, the corresponding column message_id
was still marked as NOT NULL
:
message_id | integer | | not null |
This mismatch between the model and the actual schema caused the IntegrityError
on deletion.
The Fix
Option 1: Create and Apply the Correct Migration
To resolve this properly through Django:
- Ensure the model defines
null=True
andon_delete=models.SET_NULL
. - Create a manual migration if Django doesn’t detect any changes:
- Edit the migration file to include:
- Then run the migration:
python manage.py makemigrations --empty mailing
migrations.AlterField(
model_name='sending',
name='message',
field=models.ForeignKey(
to='mailing.message',
on_delete=models.SET_NULL,
null=True,
),
)
python manage.py migrate
Option 2: Fix Directly in the Database
If you prefer a quick fix at the database level, just execute:
ALTER TABLE mailing_sending
ALTER COLUMN message_id DROP NOT NULL;
This brings the schema in line with the model.
Conclusion
This is a classic example of how model changes don’t take effect until migrations are created and applied. Always make sure your database constraints match your Django model definitions to avoid surprises like this one!
Bonus Tip: Use makemigrations
and migrate
after every model change — and check your database schema if things don't behave as expected.
Comments
Post a Comment