Fixed #36352 -- Fixed FieldError when chaining values() after annotate() with the same alias.

Signed-off-by: SaJH <wogur981208@gmail.com>
This commit is contained in:
SaJH 2025-05-18 12:46:47 +09:00
parent 0b2ed4f7c8
commit 6071fce343
2 changed files with 45 additions and 4 deletions

View file

@ -2519,10 +2519,13 @@ class Query(BaseExpression):
annotation_names.append(f)
selected[f] = f
elif f in self.annotations:
raise FieldError(
f"Cannot select the '{f}' alias. Use annotate() to "
"promote it."
)
if f not in self.annotation_select:
raise FieldError(
f"Cannot select the '{f}' alias. Use annotate() to "
"promote it."
)
annotation_names.append(f)
selected[f] = f
else:
# Call `names_to_path` to ensure a FieldError including
# annotations about to be masked as valid choices if
@ -2532,6 +2535,8 @@ class Query(BaseExpression):
selected[f] = len(field_names)
field_names.append(f)
self.set_extra_mask(extra_names)
if self.annotation_select_mask:
annotation_names = set(annotation_names) | self.annotation_select_mask
self.set_annotation_mask(annotation_names)
else:
field_names = [f.attname for f in self.model._meta.concrete_fields]

View file

@ -1206,6 +1206,42 @@ class NonAggregateAnnotationTestCase(TestCase):
self.assertEqual(qs.count(), len(qs))
def test_chained_values_annotation_fielderror(self):
qs1 = Book.objects.values("id").annotate(
author_name=F("authors__name"),
author_id=F("authors__id"),
)
qs2 = Book.objects.values("id").annotate(
author_name=F("authors__name"),
author_id=F("authors__id"),
)
combined = (qs1 | qs2).distinct()
sub = combined.filter(id=OuterRef("id")).values("author_name")
result = (
Book.objects.values("id")
.annotate(
author_id=Subquery(
sub.values("author_id").order_by("author_id")[:1],
output_field=IntegerField(),
)
)
.first()
)
self.assertIsNotNone(result)
self.assertIn("author_id", result)
qs = (
Book.objects.values("id")
.annotate(
author_name=F("authors__name"),
author_id=F("authors__id"),
)
.values("author_name")
.values("author_id")
)
self.assertGreaterEqual(len(list(qs)), 0)
class AliasTests(TestCase):
@classmethod