Charfield not enforcing null constraint

Expected behvaior: A django.db.utils.IntegrityError: NOT NULL constraint failed to be raised.

Current behvaior: An intance with an empty string as it’s value is created.

Django version=5.0.4,
Database backend: sqlite3

My model:

class Product(models.Model):
    name = models.CharField(max_length=55)
    description = models.TextField()

When I try mking an instance without specifying name and description I get no error.

product = Product()
product.save() # no error raised, No difference using Product.objects.create()

I have tried checking the DB manually and the constaint is present and works if I try to create an instance outside of Django but if it is done using Django no error is raised and the value for the field is an empty string.

Normally if you are trying to validate the model instance, you would call instance.full_clean() and that would generate a ValidationError with the given fields.
But on your case it maybe creating the values as blank string on the database.

Yes I understand that I can take it into validation level but I don’t understand the inconsistency since null=False would behave the same and raise an IntegrityError for all fields except Charfield and Textfield.

Check the null documentation.

Django’s default behavior is to allow empty strings ('' ) for CharField and TextField fields.

Try this to set explicitly the null and blank options:

class Product(models.Model):
    name = models.CharField(max_length=55, blank=False, null=False)
    description = models.TextField(blank=False, null=False)

Also for additional information on this, see: get_or_create() and create() with unspecified non-nullable fields - #7 by KenWhitesell

1 Like

Have tried this. No migrations change is detected and the behavior is still the same in the save method.

Thank you. Yes appreantly passing None explicitly will raise the expected error but not setting a value will default to an empty string which is allowed. The decision to set an empty string as the default value doesn’t make much sense to me.

if you want run valid before save object, you should call model.full_clean() as leandrodesouzadev said.

if you do not call full_clean, django do not run validate.

obj = model()
obj.full_clean()
obj.save()

Note, however, that like Model.full_clean(), a model’s clean() method is not invoked when you call your model’s save() metho