The IntegrityError: null value in column "field_name" violates not-null constraint means your Django application tried to save a record with a NULL value for a database column that explicitly forbids it, even though your Django model field was configured to allow null=True.
This happens because Django’s ORM and the database schema can get out of sync. The database has a strict NOT NULL constraint on a column, but Django’s model definition might be telling a different story, or a previous migration might have failed to update the schema correctly.
Here are the common causes and how to fix them:
-
Database Schema Mismatch (Most Common): Your Django model has
null=True(or it’s the default for nullable fields likeCharField), but the database column was created without allowing NULLs, or a previous migration that should have altered the column to allow NULLs failed.- Diagnosis:
Then, in your database shell (e.g.,python manage.py dbshellpsql,mysql):
Look for the specific column (-- For PostgreSQL: \d your_table_name; -- For MySQL: DESCRIBE your_table_name;field_name). If it showsNOT NULLorNOunder the NULL column, that’s your problem. - Fix: Run
makemigrationsandmigrateagain. If that doesn’t work, you might need to manually alter the column in the database schema.
If migration still doesn’t fix it, manually alter the column:python manage.py makemigrations python manage.py migrate
After this, run# For PostgreSQL: ALTER TABLE your_table_name ALTER COLUMN field_name DROP NOT NULL; # For MySQL: ALTER TABLE your_table_name MODIFY field_name VARCHAR(255) NULL; -- Replace VARCHAR(255) with your actual field type and max_lengthpython manage.py makemigrationsagain to ensure Django’s migration history reflects the current schema state. - Why it works: This directly removes the
NOT NULLconstraint from the database, aligning it with what your Django model expects.
- Diagnosis:
-
New Field Added to Existing Table Without Default: You added a new
CharFieldorTextFieldto an existing model and setnull=Trueandblank=True, but you didn’t provide adefaultvalue. When Django tries to create this column on a table that already has rows, it needs to know what value to put in the new column for existing rows. Ifnull=Truebut nodefault, the database might balk if it has its own implicitNOT NULLrule for new columns.- Diagnosis: Similar to cause 1, check the schema for the new column and see if it’s marked
NOT NULL. Also, review your model definition for the new field. - Fix: Add a
defaultvalue to your model field.
Then run migrations:class MyModel(models.Model): existing_field = models.CharField(max_length=100) # Add a default value new_nullable_field = models.CharField(max_length=100, null=True, blank=True, default='')python manage.py makemigrations python manage.py migrate - Why it works: Providing a
defaulttells the database what value to insert into the new column for all existing rows, satisfying anyNOT NULLconstraints it might enforce during column creation. An empty string''is a common default for text fields.
- Diagnosis: Similar to cause 1, check the schema for the new column and see if it’s marked
-
default=Nonevs.null=TrueConfusion: Sometimes people setdefault=Noneexplicitly, thinking it’s the same asnull=True. WhileNonecan be represented asNULLin the database,default=Noneon a field that doesn’t havenull=Truewill cause this error. Thenull=Truetells Django to allow NULLs;default=Nonetells Django what value to use if no value is provided during object creation.- Diagnosis: Check your model field definition. If it has
default=Nonebut lacksnull=True, and the database column isNOT NULL, that’s the issue. - Fix: Ensure
null=Trueis present on the model field.
Then run migrations.class MyModel(models.Model): # Incorrect if database column is NOT NULL # problematic_field = models.CharField(max_length=50, default=None) # Corrected problematic_field = models.CharField(max_length=50, null=True, blank=True, default=None) # Or if you want a specific default other than None/NULL: # problematic_field = models.CharField(max_length=50, default='') - Why it works: Explicitly allowing
null=Truein the Django model definition is crucial for the ORM to generate the correct SQL for databases that support NULL values.
- Diagnosis: Check your model field definition. If it has
-
Constraint on a Different Field: The error message might point to
field_name, but the actualNOT NULLconstraint could be on a related field, especially if you’re usingForeignKeyand not settingon_deleteorrelated_namecorrectly, or if you’re trying to save an object where a related object isNonebut the foreign key column isNOT NULL.- Diagnosis: Examine the traceback carefully. If the error mentions a
ForeignKeyorOneToOneField, check the model definition of the related model and the database schema for that foreign key column. - Fix: Ensure the foreign key field in the database allows NULLs if you intend to have objects without a related instance.
Run migrations. If the database column is alreadyclass RelatedModel(models.Model): name = models.CharField(max_length=100) class MyModel(models.Model): # If you want to allow MyModel instances without a RelatedModel related_instance = models.ForeignKey(RelatedModel, on_delete=models.SET_NULL, null=True, blank=True)NOT NULL, you’ll need to manually alter it as in cause 1. - Why it works: By setting
null=Trueon theForeignKeyfield, you instruct Django to create a nullable foreign key column in the database, which then allows related objects to be optional.
- Diagnosis: Examine the traceback carefully. If the error mentions a
-
Manual SQL in Migrations: If you have custom SQL in a migration that explicitly sets
NOT NULLon a column, but your Django model field hasnull=True, this will cause a conflict.- Diagnosis: Review your migration files in your
migrations/directory for anyRunSQLoperations that might be altering the column in question. - Fix: Either remove the
NOT NULLconstraint from your custom SQL or update your Django model field to reflect theNOT NULLconstraint (removenull=True).
Modify this SQL to# Example custom SQL in a migration # operations = [ # migrations.RunSQL( # "ALTER TABLE your_table_name ALTER COLUMN field_name SET NOT NULL;", # "ALTER TABLE your_table_name ALTER COLUMN field_name DROP NOT NULL;" # ), # ]DROP NOT NULLor remove the operation entirely if it conflicts with your model. - Why it works: Synchronizing the custom SQL with the model definition ensures both the database schema and Django’s understanding of it are consistent.
- Diagnosis: Review your migration files in your
-
Third-Party App Overrides: Sometimes, a third-party Django app might introduce models or migrations that, unintentionally, create
NOT NULLconstraints that conflict with your local models or expectations.- Diagnosis: If the error occurs during installation or migration of a third-party app, examine that app’s models and migration files.
- Fix: You might need to fork the app and adjust its migrations, or apply manual database schema changes (with caution) to allow NULLs on the problematic column.
- Why it works: This is a workaround to align the third-party’s schema with your application’s needs.
After applying any of these fixes, remember to run python manage.py makemigrations and python manage.py migrate to ensure your database schema is updated.
The next error you’ll likely hit after fixing this is OperationalError: (1050, "Table 'your_table_name' already exists") if you’ve previously tried to create a table that already exists, or a ManyToManyField related error if you’re dealing with a many-to-many relationship that has its own constraints.