[Django]-Object created even if field was required

4👍

Note: You don’t to have provide null=False,blank=False in your fields because those are the values used by default.(See the Django Field __int__ signature.).

def __init__(self, verbose_name=None, name=None, primary_key=False,
                 max_length=None, unique=False, blank=False, null=False,
                 db_index=False, rel=None, default=NOT_PROVIDED, editable=True,
                 serialize=True, unique_for_date=None, unique_for_month=None,
                 unique_for_year=None, choices=None, help_text='', db_column=None,
                 db_tablespace=None, auto_created=False, validators=(),
                 error_messages=None):

By default all the fields in database are created with NOT NULL constraint. If you set null=True for a particular field, then django sets NULL on the column in your DB. It’s the database equivalent of Python’s None keyword.

Example with null argument

Assume that I have the following Mymodel in my my_app and I set email field to null=True.

class MyModel(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(max_length=100, null=True)
    password = models.CharField(max_length=120)
    email_notification = models.BooleanField()

In Shell,

>> from my_app.models import MyModel

>> new = MyModel.objects.create(name="ok",
                                password="dsfdsfdsfdsfsfds",
                                email_notification=1)
>> new.email == None
>> True # As you can see Django sets db value 
        # as NULL and when we query the data it converts back to Python `None` object.

Example without null argument

Assume that I have the following Mymodel in my my_app.(remember null will be False by default)

class MyModel(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(max_length=100)
    password = models.CharField(max_length=120)
    email_notification = models.BooleanField()

In Shell,

>> from my_app.models import MyModel
>> new_obj = MyModel.objects.create(name="test",
                                password="test",
                                email_notification=1)
>> new_obj.email == ''
>> True

Ie,Django CharField and TextField the default values are stored in the DB as an empty string (''). In other words, if you create an object without providing values for a CharField(or a TextField) under the hood Django invokes the get_default method and returns '' (only in this case). This value will be stored in the database.

The following is the source code of get_default method.

def get_default(self):
    """Return the default value for this field."""
    return self._get_default()

@cached_property
def _get_default(self):
    if self.has_default():
        if callable(self.default):
            return self.default
        return lambda: self.default

    if not self.empty_strings_allowed or self.null and not connection.features.interprets_empty_strings_as_nulls:
        return return_None
    return str  # return empty string

Let’s answer your question:

Why object got created,even if email field was mandatory?

The answer is EmailField is an instance of CharField Hence default value '' will be used while creating an object in database. That is why you are not getting django.db.utils.IntegrityError.

>> new_obj = Mymodel.objects.create(name='tes1t', password='test1', email_notification=1)
>>> new_obj.email
''

Also if I go to the admin panel and open that object and click save then
it raises an error indicating that email is required

Remember blank is different from null. null is purely database-related, whereas blank is validation-related. So when you create an object directly in Python code, or execute raw SQL yourself, you are actually bypassing all of Django’s input validation. But in admin, Django is validating the input through the model form. Since in your case blank is set to False(blank not allowed), model form will raise Email is required Error.

Here is the relevant Django documentation for blank argument.

Field.blank

If True, the field is allowed to be blank. Default is False. Note
that this is different than null. null is purely database-related,
whereas blank is validation-related. If a field has blank=True, form
validation will allow entry of an empty value. If a field has
blank=False, the field will be required.

Additional resources

1👍

There is no issue with django you will have to create proper Django Model Form validation so that the empty string isn’t ignored and it will raise an error for the blank field.

Leave a comment