Opened 7 weeks ago
Last modified 5 weeks ago
#36518 closed Bug
full_clean crashes on model with both a CheckConstraint and a GeneratedField with a Case expression (possible regression in Django 5.2) — at Initial Version
Reported by: | Olivier Dalang | Owned by: | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 5.2 |
Severity: | Release blocker | Keywords: | |
Cc: | Olivier Dalang, Mark Gensler, Simon Charette, Mariusz Felisiak | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
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
# 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(), )
# 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'...