﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
36518	full_clean crashes on model with both a CheckConstraint and a GeneratedField with a Case expression	Olivier Dalang	Simon Charette	"Hello !

I think I ran accross a regression when upgrading a model containing a CheckConstraint and a GeneratedField (that are unrelated) from Django 5.1 to 5.2. 

Below is a simplified case that reproduces the issue.

I found is a similar ticket: https://code.djangoproject.com/ticket/34871 (affecting 4.2 already, and thus not flagged as regression, for a slightly simpler use case). 

That ticket links to recent PR which could quite likely has introduced this regression: https://github.com/django/django/pull/19218

I'm not yet familiar with contributing to Django, and fear this is (way) above my level to fix, but please let me know if I can do anything to help fixing this, as it currently prevents us from upgrading.

Cheers !!

Olivier


{{{#!python
# models.py

class MyModel(models.Model):
    class Meta:
        constraints = [
            models.CheckConstraint(name=""age_valid"", check=Q(age__lt=100)),
        ]

    age = models.IntegerField()
    is_old_enough = models.GeneratedField(
        expression=Case(
            When(
                age__gte=18,
                then=Value(True),
            ),
            default=Value(False),
        ),
        db_persist=True,
        output_field=models.BooleanField(),
    )
}}}


{{{#!python
# tests.py

class MyTests(TestCase):
    def test_fullclean(self):
        bob = MyModel.objects.create(age=17)
        bob.full_clean()
}}}

The test succeeds on Django 5.1, but fails on 5.2.


{{{
> uv run --with django==5.2.4 manage.py test
Found 1 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
E
======================================================================
ERROR: test_fullclean (myproj.myapp.tests.MyTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ""/home/app/myproj/myapp/tests.py"", line 8, in test_fullclean
    bob.full_clean()
  File ""/home/cache/archive-v0/kkaSi9So5gXBgF1hYbu9X/lib/site-packages/django/db/models/base.py"", line 1674, in full_clean
    self.validate_constraints(exclude=exclude)
  File ""/home/cache/archive-v0/kkaSi9So5gXBgF1hYbu9X/lib/site-packages/django/db/models/base.py"", line 1622, in validate_constraints
    constraint.validate(model_class, self, exclude=exclude, using=using)
  File ""/home/cache/archive-v0/kkaSi9So5gXBgF1hYbu9X/lib/site-packages/django/db/models/constraints.py"", line 261, in validate
    against = instance._get_field_expression_map(meta=model._meta, exclude=exclude)
  File ""/home/cache/archive-v0/kkaSi9So5gXBgF1hYbu9X/lib/site-packages/django/db/models/base.py"", line 1372, in _get_field_expression_map
    generated_field.expression.replace_expressions(replacements),
  File ""/home/cache/archive-v0/kkaSi9So5gXBgF1hYbu9X/lib/site-packages/django/db/models/expressions.py"", line 427, in replace_expressions
    [
  File ""/home/cache/archive-v0/kkaSi9So5gXBgF1hYbu9X/lib/site-packages/django/db/models/expressions.py"", line 428, in <listcomp>
    expr.replace_expressions(replacements) if expr else None
  File ""/home/cache/archive-v0/kkaSi9So5gXBgF1hYbu9X/lib/site-packages/django/db/models/expressions.py"", line 427, in replace_expressions
    [
  File ""/home/cache/archive-v0/kkaSi9So5gXBgF1hYbu9X/lib/site-packages/django/db/models/expressions.py"", line 428, in <listcomp>
    expr.replace_expressions(replacements) if expr else None
AttributeError: 'Q' object has no attribute 'replace_expressions'
----------------------------------------------------------------------
Ran 1 test in 0.003s

FAILED (errors=1)
Destroying test database for alias 'default'...
}}}

{{{
> uv run --with django==5.1.11 manage.py test
Found 1 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
----------------------------------------------------------------------
Ran 1 test in 0.002s

OK
Destroying test database for alias 'default'...
}}}
"	Bug	closed	Database layer (models, ORM)	5.2	Release blocker	fixed		Olivier Dalang Mark Gensler Simon Charette Mariusz Felisiak	Ready for checkin	1	0	0	0	0	0
