diff options
| author | willzhao <gnomeek@outlook.com> | 2023-08-31 07:51:44 +0000 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2023-09-01 11:25:00 +0200 |
| commit | acfb42752259c3f920ffd20d6eef83b3c6f75cf7 (patch) | |
| tree | 552ba3871fcacd330d58a91c91a17fddaa85bf46 | |
| parent | 55a0b9c32ebae957b95a9a55846692837e2ff39b (diff) | |
[4.2.x] Fixed #34803 -- Fixed queryset crash when filtering againts deeply nested OuterRef annotations.
Thanks Pierre-Nicolas Rigal for the report.
Regression in c67ea79aa981ae82595d89f8018a41fcd842e7c9.
Backport of 9cc0d7f7f85cecc3ad15bbc471fe6a08e4f515b6 from main
| -rw-r--r-- | AUTHORS | 1 | ||||
| -rw-r--r-- | django/db/models/expressions.py | 1 | ||||
| -rw-r--r-- | docs/releases/4.2.5.txt | 3 | ||||
| -rw-r--r-- | tests/expressions/models.py | 4 | ||||
| -rw-r--r-- | tests/expressions/tests.py | 30 |
5 files changed, 39 insertions, 0 deletions
@@ -1021,6 +1021,7 @@ answer newbie questions, and generally made Django that much better: Will Ayd <william.ayd@icloud.com> William Schwartz <wkschwartz@gmail.com> Will Hardy <django@willhardy.com.au> + Will Zhao <www.gnomeek@gmail.com> Wilson Miner <wminer@gmail.com> Wim Glenn <hey@wimglenn.com> wojtek diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py index c6443892e2..cc78ac8773 100644 --- a/django/db/models/expressions.py +++ b/django/db/models/expressions.py @@ -879,6 +879,7 @@ class ResolvedOuterRef(F): class OuterRef(F): contains_aggregate = False + contains_over_clause = False def resolve_expression(self, *args, **kwargs): if isinstance(self.name, self.__class__): diff --git a/docs/releases/4.2.5.txt b/docs/releases/4.2.5.txt index fe216cadb3..d88ece91e6 100644 --- a/docs/releases/4.2.5.txt +++ b/docs/releases/4.2.5.txt @@ -21,3 +21,6 @@ Bugfixes * Fixed a regression in Django 4.2.2 that caused an unnecessary selection of a non-nullable ``ManyToManyField`` without a natural key during serialization (:ticket:`34779`). + +* Fixed a regression in Django 4.2 that caused a crash of a queryset when + filtering against deeply nested ``OuterRef()`` annotations (:ticket:`34803`). diff --git a/tests/expressions/models.py b/tests/expressions/models.py index 35985dc5f0..0a8a0a6584 100644 --- a/tests/expressions/models.py +++ b/tests/expressions/models.py @@ -8,6 +8,9 @@ from django.db import models class Manager(models.Model): name = models.CharField(max_length=50) + secretary = models.ForeignKey( + "Employee", models.CASCADE, null=True, related_name="managers" + ) class Employee(models.Model): @@ -15,6 +18,7 @@ class Employee(models.Model): lastname = models.CharField(max_length=50) salary = models.IntegerField(blank=True, null=True) manager = models.ForeignKey(Manager, models.CASCADE, null=True) + based_in_eu = models.BooleanField(default=False) def __str__(self): return "%s %s" % (self.firstname, self.lastname) diff --git a/tests/expressions/tests.py b/tests/expressions/tests.py index 7db6013819..a928b76bab 100644 --- a/tests/expressions/tests.py +++ b/tests/expressions/tests.py @@ -871,6 +871,36 @@ class BasicExpressionsTests(TestCase): ).filter(ceo_company__isnull=False) self.assertEqual(qs.get().ceo_company, "Test GmbH") + def test_annotation_with_deeply_nested_outerref(self): + bob = Employee.objects.create(firstname="Bob", based_in_eu=True) + self.max.manager = Manager.objects.create(name="Rock", secretary=bob) + self.max.save() + qs = Employee.objects.filter( + Exists( + Manager.objects.filter( + Exists( + Employee.objects.filter( + pk=OuterRef("secretary__pk"), + ) + .annotate( + secretary_based_in_eu=OuterRef(OuterRef("based_in_eu")) + ) + .filter( + Exists( + Company.objects.filter( + # Inner OuterRef refers to an outer + # OuterRef (not ResolvedOuterRef). + based_in_eu=OuterRef("secretary_based_in_eu") + ) + ) + ) + ), + secretary__pk=OuterRef("pk"), + ) + ) + ) + self.assertEqual(qs.get(), bob) + def test_pickle_expression(self): expr = Value(1) expr.convert_value # populate cached property |
