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=Trueandon_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