get_or_create() and create() with unspecified non-nullable fields

Hello!
I have the following model:

class MyModel(models.Model):
    
    title = models.CharField(null=False, max_length=50)
    slug = models.SlugField(null=False)

    def save(self, *args, **kwargs):
        new_slug = slugify(self.title)
        if not self.slug or self.slug != new_slug:
            self.slug=new_slug
        return super().save(*args, **kwargs)

When I use MyModel.objects.get_or_create(id=<some_new_id>) or MyModel.objects.create() with empty arguments like that, they create objects and force them into the database even though non-nullable fields are not specified, which I expected to raise an error.
Is there something I am missing?
The behaviour is the same for sqlite3 and MySQL. Is suspected there was something wrong with my extending save but any new model created behaves similarly. Why is the null=False rule not enforced in the Manager’s create and get_or_create() methods, or am I missing something?

Hi @cliff688. null indicates what value should be stored if the field is empty. From the docs:

null
If True, Django will store empty values as NULL in the database. Default is False.

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.

So you should use blank=False to indicate that a field is required.

There is a difference between an empty string ('') and a null value in the database. If you do a get on those rows being saved, you’ll find that what is stored are empty strings.

If you try to do something like MyModel.objects.create(title=None), you will get the expected error.

If you specify default=None in your title field, you will also get the expected error.

But by default, it appears that MyModel.objects.create() will set the undefined fields to '', and so no error is generated.

1 Like

This isn’t quite accurate in the context of the original question. As you quoted:

This only applies during form validation, and would not affect a direct ORM call such as MyModel.objects.create()

Ah yes, of course. Thanks for the correction!

Thank you.
Where in the docs might I find more information about this?
Also why does it act that way by default? Is there a ticket/forum I can look at to understand why it was designed that way?
I am still trying to figure out my way around. Thank you

I’m not currently finding anything in the docs specifically addressing this. (I may be missing something obvious here.)

It is somewhat covered in the Field.null docs:

Avoid using null on string-based fields such as CharField and TextField.

and

In most cases, it’s redundant to have two possible values for “no data;” the Django convention is to use the empty string, not NULL .

From what I understand from what I’m reading, it looks like it’s covered by the code in django.db.models.fields.__init__. The base Field class has a class variable named empty_strings_allowed, which is set True in this class, but set to False in most other non-charfield classes. This variable is used by the _get_default method to determine whether this method returns an empty string or None.

Digging into the git history, it looks like this same basic mechanism has been in place since version 0.95, so it has basically always been this way. You’d have to go all the way back to the original design to try and find out why. (This also appears to pre-date trac, so you’re not likely to find a ticket addressing it.)

1 Like