#35638: validate_constraints() fails on models with fields using db_default
-------------------------------------+-------------------------------------
Reporter: David Sanders | Type: Bug
Status: new | Component: Database
| layer (models, ORM)
Version: dev | Severity: Normal
Keywords: db_default | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Follow up to #35223
Related forum thread:
https://forum.djangoproject.com/t/proposal-to-have-
db-default-considered-in-model-forms/33358/3
Given the model
{{{
class Foo(models.Model):
bar = models.CharField(db_default="bar")
class Meta:
constraints = [
models.CheckConstraint(check=models.Q(bar="bar"),
name="is_bar"),
]
}}}
validating constraints should ideally not fail but currently does:
{{{
>>> foo = Foo()
>>> foo.validate_constraints()
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/path/to/django/django/db/models/base.py", line 1598, in
validate_constraints
raise ValidationError(errors)
django.core.exceptions.ValidationError: {'__all__': ['Constraint “is_bar”
is violated.']}
}}}
I couldn't find an easy workaround for this.
If I apply this small patch to `Q.check()`, then `validate_constraints()`
uses the default expression and runs a suitable check query. Perhaps can
take this as a starting point and add something similar to Django?
{{{
index 1bf396723e..5380cc17d0 100644
--- a/django/db/models/query_utils.py
+++ b/django/db/models/query_utils.py
@@ -120,12 +120,16 @@ class Q(tree.Node):
"""
# Avoid circular imports.
from django.db.models import BooleanField, Value
+ from django.db.models.expressions import DatabaseDefault
from django.db.models.functions import Coalesce
from django.db.models.sql import Query
from django.db.models.sql.constants import SINGLE
query = Query(None)
for name, value in against.items():
+ # not ideal, value is wrapped in a Value by
Model._get_field_value_map()
+ if isinstance(getattr(value, "value"), DatabaseDefault):
+ value = value.field.db_default
if not hasattr(value, "resolve_expression"):
value = Value(value)
query.add_annotation(value, name, select=False)
}}}
--
Ticket URL: <
https://code.djangoproject.com/ticket/35638>
Django <
https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.