summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVinko Mlačić <vinkomlacic@outlook.com>2025-01-28 22:57:32 +0100
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2025-01-30 12:18:08 +0100
commitd567e3a52e8b3ef0f830e07b602ae1382657eb07 (patch)
tree29cd93f3ae09c575d090a2834c5c01fcd381c863
parentdfaf8aa6c627df1357947d69a6c1073707e62523 (diff)
[5.2.x] Fixed #36155 -- Improved error handling when annotate arguments require an alias.
Regression in ed0cbc8d8b314e3b4a0305d0be3cf366d8ee4a74. Backport of c6ace896a2da73356f7c9a655bbe32a0e3ce0435 from main.
-rw-r--r--AUTHORS1
-rw-r--r--django/db/models/query.py6
-rw-r--r--tests/annotations/tests.py18
3 files changed, 23 insertions, 2 deletions
diff --git a/AUTHORS b/AUTHORS
index 0648241267..9a76e8879e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1053,6 +1053,7 @@ answer newbie questions, and generally made Django that much better:
Vinay Karanam <https://github.com/vinayinvicible>
Vinay Sajip <vinay_sajip@yahoo.co.uk>
Vincent Foley <vfoleybourgon@yahoo.ca>
+ Vinko Mlačić <vinkomlacic@outlook.com>
Vinny Do <vdo.code@gmail.com>
Vitaly Babiy <vbabiy86@gmail.com>
Vitaliy Yelnik <velnik@gmail.com>
diff --git a/django/db/models/query.py b/django/db/models/query.py
index 1730aca16d..aaeb8d30cc 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -1647,14 +1647,16 @@ class QuerySet(AltersData):
)
annotations = {}
for arg in args:
- # The default_alias property may raise a TypeError.
+ # The default_alias property raises TypeError if default_alias
+ # can't be set automatically or AttributeError if it isn't an
+ # attribute.
try:
if arg.default_alias in kwargs:
raise ValueError(
"The named annotation '%s' conflicts with the "
"default name for another annotation." % arg.default_alias
)
- except TypeError:
+ except (TypeError, AttributeError):
raise TypeError("Complex annotations require an alias")
annotations[arg.default_alias] = arg
annotations.update(kwargs)
diff --git a/tests/annotations/tests.py b/tests/annotations/tests.py
index 29660a827e..5df958c333 100644
--- a/tests/annotations/tests.py
+++ b/tests/annotations/tests.py
@@ -969,6 +969,24 @@ class NonAggregateAnnotationTestCase(TestCase):
):
Book.objects.annotate(BooleanField(), Value(False), is_book=True)
+ def test_complex_annotations_must_have_an_alias(self):
+ complex_annotations = [
+ F("rating") * F("price"),
+ Value("title"),
+ Case(When(pages__gte=400, then=Value("Long")), default=Value("Short")),
+ Subquery(
+ Book.objects.filter(publisher_id=OuterRef("pk"))
+ .order_by("-pubdate")
+ .values("name")[:1]
+ ),
+ Exists(Book.objects.filter(publisher_id=OuterRef("pk"))),
+ ]
+ msg = "Complex annotations require an alias"
+ for annotation in complex_annotations:
+ with self.subTest(annotation=annotation):
+ with self.assertRaisesMessage(TypeError, msg):
+ Book.objects.annotate(annotation)
+
def test_chaining_annotation_filter_with_m2m(self):
qs = (
Author.objects.filter(