1
0
mirror of https://github.com/django/django.git synced 2025-03-06 15:32:33 +00:00

[5.2.x] Fixed #36155 -- Improved error handling when annotate arguments require an alias.

Regression in ed0cbc8d8b314e3b4a0305d0be3cf366d8ee4a74.

Backport of c6ace896a2da73356f7c9a655bbe32a0e3ce0435 from main.
This commit is contained in:
Vinko Mlačić 2025-01-28 22:57:32 +01:00 committed by Sarah Boyce
parent dfaf8aa6c6
commit d567e3a52e
3 changed files with 23 additions and 2 deletions

View File

@ -1053,6 +1053,7 @@ answer newbie questions, and generally made Django that much better:
Vinay Karanam <https://github.com/vinayinvicible> Vinay Karanam <https://github.com/vinayinvicible>
Vinay Sajip <vinay_sajip@yahoo.co.uk> Vinay Sajip <vinay_sajip@yahoo.co.uk>
Vincent Foley <vfoleybourgon@yahoo.ca> Vincent Foley <vfoleybourgon@yahoo.ca>
Vinko Mlačić <vinkomlacic@outlook.com>
Vinny Do <vdo.code@gmail.com> Vinny Do <vdo.code@gmail.com>
Vitaly Babiy <vbabiy86@gmail.com> Vitaly Babiy <vbabiy86@gmail.com>
Vitaliy Yelnik <velnik@gmail.com> Vitaliy Yelnik <velnik@gmail.com>

View File

@ -1647,14 +1647,16 @@ class QuerySet(AltersData):
) )
annotations = {} annotations = {}
for arg in args: 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: try:
if arg.default_alias in kwargs: if arg.default_alias in kwargs:
raise ValueError( raise ValueError(
"The named annotation '%s' conflicts with the " "The named annotation '%s' conflicts with the "
"default name for another annotation." % arg.default_alias "default name for another annotation." % arg.default_alias
) )
except TypeError: except (TypeError, AttributeError):
raise TypeError("Complex annotations require an alias") raise TypeError("Complex annotations require an alias")
annotations[arg.default_alias] = arg annotations[arg.default_alias] = arg
annotations.update(kwargs) annotations.update(kwargs)

View File

@ -969,6 +969,24 @@ class NonAggregateAnnotationTestCase(TestCase):
): ):
Book.objects.annotate(BooleanField(), Value(False), is_book=True) 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): def test_chaining_annotation_filter_with_m2m(self):
qs = ( qs = (
Author.objects.filter( Author.objects.filter(