From ed6b14d4591e536985222b61cb8b83908d58140d Mon Sep 17 00:00:00 2001 From: Sergey Fedoseev Date: Wed, 1 Jul 2020 14:01:46 +0500 Subject: [PATCH] Refs #28621 -- Fixed crash of annotations with nested OuterRef. --- django/db/models/expressions.py | 2 ++ tests/expressions/tests.py | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py index 7987b1e747..d913658291 100644 --- a/django/db/models/expressions.py +++ b/django/db/models/expressions.py @@ -584,6 +584,8 @@ class ResolvedOuterRef(F): class OuterRef(F): + contains_aggregate = False + def resolve_expression(self, *args, **kwargs): if isinstance(self.name, self.__class__): return self.name diff --git a/tests/expressions/tests.py b/tests/expressions/tests.py index ed87d99fd5..72f95f0194 100644 --- a/tests/expressions/tests.py +++ b/tests/expressions/tests.py @@ -710,6 +710,22 @@ class BasicExpressionsTests(TestCase): ).get(pk=self.gmbh.pk) self.assertEqual(gmbh_salary.max_ceo_salary_raise, 2332) + def test_annotation_with_nested_outerref(self): + self.gmbh.point_of_contact = Employee.objects.get(lastname='Meyer') + self.gmbh.save() + inner = Employee.objects.annotate( + outer_lastname=OuterRef(OuterRef('lastname')), + ).filter(lastname__startswith=Left('outer_lastname', 1)) + qs = Employee.objects.annotate( + ceo_company=Subquery( + Company.objects.filter( + point_of_contact__in=inner, + ceo__pk=OuterRef('pk'), + ).values('name'), + ), + ).filter(ceo_company__isnull=False) + self.assertEqual(qs.get().ceo_company, 'Test GmbH') + def test_pickle_expression(self): expr = Value(1, output_field=IntegerField()) expr.convert_value # populate cached property