#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.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/01070190fd6d1a8d-8fad2846-af46-4fe0-9f42-5a6faf03f98d-000000%40eu-central-1.amazonses.com.

Reply via email to