Django: NULL error on model field despite default value

My model class is defined as follows: [django 5.0]

class Vendor(models.Model):
    """
    ORM representing vendors

    Relationships:
    A vendor may have many documents
    """

    id = models.AutoField(
        primary_key=True,
    )
    name = models.CharField(
        max_length=255,
        blank=True,
        db_default='',
        default='',
    )
    logo_uri = models.CharField(
        max_length=255,
        blank=True,
        db_default='',
        default='',
    )
    web_url = models.CharField(
        max_length=255,
        blank=True,
        db_default='',
        default=None,
    )
    created_on = models.DateTimeField(
        auto_now_add=True,
        null=False,
    )

    def __str__(self) -> str:
        return f"{self.name}"
    
    class Meta:
        ordering =  ["created_on"]
        verbose_name = "vendor"
        verbose_name_plural = "vendors"

I am using MySQL and have checked the database DDL - the default value for specified columns is set as ''. If I insert using a SQL statement directly in MySQL it works fine and default values are assigned as appropriate -

INSERT INTO `core_vendor`
(`name`,
`created_on`)
VALUES
('TES',
  NOW()
);

However when I programatically try to insert via django -

vendor = Vendor()
vendor.name='TES2'
vendor.save()

I receive an error

django.db.utils.IntegrityError: (1048, "Column 'web_url' cannot be null")

Though web_url has a default value assigned at django and DB level. Any thoughts on where I am incorrect?

The db_default is used on case the value is missing, but here you have set the default=None. db_default is thus what Django will generate as SQL when constructing the table. It will thus write something like

CREATE TABLE vendor (
 -- …
 web_url varchar(255) DEFAULT ''
)

but then, because of the default=None, it will make a query:

INSERT INTO vendor (web_url)
VALUES (NULL);

since you pass a value explicitly, it thus errors.

This is also explained in the documentation on db_default=… [Django-doc]:

If both db_default and Field.default are set, default will take precedence when creating instances in Python code. db_default will still be set at the database level and will be used when inserting rows outside of the ORM or when adding a new field in a migration.

Back to Top