[Django] #36518: full_clean crashes on model with both a CheckConstraint and a GeneratedField with a Case expression (possible regression in Django 5.2)

2 views
Skip to first unread message

Django

unread,
Jul 22, 2025, 12:30:23 PMJul 22
to django-...@googlegroups.com
#36518: full_clean crashes on model with both a CheckConstraint and a
GeneratedField with a Case expression (possible regression in Django 5.2)
-------------------------------------+-------------------------------------
Reporter: Olivier Dalang | Type:
| Uncategorized
Status: new | Component: Database
| layer (models, ORM)
Version: 5.2 | Severity: Normal
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Hello !

I think I ran accross a regression when upgrading the 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'...
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/36518>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Jul 22, 2025, 12:39:28 PMJul 22
to django-...@googlegroups.com
#36518: full_clean crashes on model with both a CheckConstraint and a
GeneratedField with a Case expression (possible regression in Django 5.2)
-------------------------------------+-------------------------------------
Reporter: Olivier Dalang | Owner: (none)
Type: Uncategorized | Status: new
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Description changed by Olivier Dalang:

Old description:
New description:

Hello !

I think I ran accross a regression when upgrading a model containing a
--
Ticket URL: <https://code.djangoproject.com/ticket/36518#comment:1>
Reply all
Reply to author
Forward
0 new messages