We skipped model validation of db_default values to fix a crash in 5.0.4 (PR).
For generated values, that makes sense, and aligns with GeneratedField.
But for literal values, I find that surprising. Can’t we resolve the db_default expression to find out if it’s a literal value, and validate that?
Skipping model validation like this is, I think, unexpected – it’s not difficult for me to imagine db_defaults and validation requirements either getting out of sync or being intentionally different (Django-writes being subject to stricter requirements than direct-writes):
from django.core import validators
from django.db import models
class Article(models.Model):
slug = models.SlugField(db_default="not*sluggable")
def __str__(self):
return self.slug
def run():
instance = Article()
instance.full_clean() # succeeds
instance.save()
print(f'Created: {instance}')
# instance.full_clean() # fails
Direct validator usage also doesn’t work:
def run():
instance = Article()
instance._meta.get_field("slug").run_validators(instance.slug)
File "/usr/local/lib/python3.12/site-packages/django/core/validators.py", line 503, in clean
return len(x)
^^^^^^
TypeError: object of type 'DatabaseDefault' has no len()