When I define a non nullable field in django it allows me to save a model instance without specifying any value for this non-nullable field. This is not what I would expect. How can I force this to yield an error?
Postgres 9.1 django 2.1 windows python 3.6
from django.db import models
class Wwtp(models.Model):
name = models.CharField(max_length=100, null=False,
blank=False, unique=True)
short_name = models.CharField(
max_length=10, null=False, blank=False, unique=True)
As expected, I am not allowed to save it with an explicit empty short_name.
mdl.Wwtp.objects.create(name='Wwtp4', short_name=None)
But I am allowed to save an instance of Wwtp without specifying short_name:
mdl.Wwtp.objects.create(name='Wwtp4')
and when I try:
mdl.Wwtp.objects.create()
it gives me
django.db.utils.IntegrityError: duplicate key value violates unique constraint "api_wwtp_short_name_key"
DETAIL: Key (short_name)=() already exists.
Apparently django filled the database with an empty value for short_name
while it is not allowed to do so... How can I force the database to not allow this?
You can't with CharField
. The empty value is an empty string ''
, not NULL
. You already have blank=False
set, so if you clean your model or model forms before saving them, you'll catch that. But it cannot be enforced at the database level.
Note that blank=False, null=False
is the default, so you really don't have to specify that.
Also, if you really only want to support PostgreSQL, you could make a custom migration using RunSQL
to create your column on the table, manually adding the SQL needed to add the constraint (e.g. using CHECK
). See here for how to ensure Django also knows the column was created and doesn't try to add it in the next migration. There's an example here.
[Edit] In Django 2.2, you can add a CheckConstraint
in the model's Meta
class constraints
attribute:
from django.db.models import CheckConstraint, Q
(...)
class Meta:
constraints = [
CheckConstraint(
check=~Q(name=''),
name='name_not_empty'),
CheckConstraint(
check=~Q(short_name=''),
name='short_name_not_empty']