1
0
mirror of https://github.com/django/django.git synced 2025-10-28 08:06:09 +00:00

Fixed #36288 -- Addressed improper handling of duplicates in values_list().

Now that selected aliases are stored in sql.Query.selected: dict[str, Any]
the values_list() method must ensures that duplicate field name references are
assigned unique aliases.

Refs #28900.

Regression in 65ad4ade74.

Thanks Claude for the report.
This commit is contained in:
Simon Charette
2025-04-02 18:53:36 -04:00
committed by Sarah Boyce
parent 2d1ac1dce8
commit 21f8be76d4
4 changed files with 35 additions and 16 deletions

View File

@@ -1371,24 +1371,33 @@ class QuerySet(AltersData):
"field."
)
field_names = {f for f in fields if not hasattr(f, "resolve_expression")}
field_names = {f: False for f in fields if not hasattr(f, "resolve_expression")}
_fields = []
expressions = {}
counter = 1
for field in fields:
field_name = field
expression = None
if hasattr(field, "resolve_expression"):
field_id_prefix = getattr(
field_name = getattr(
field, "default_alias", field.__class__.__name__.lower()
)
while True:
field_id = field_id_prefix + str(counter)
expression = field
# For backward compatibility reasons expressions are always
# prefixed with the counter even if their default alias doesn't
# collide with field names. Changing this logic could break
# some usage of named=True.
seen = True
elif seen := field_names[field_name]:
expression = F(field_name)
if seen:
field_name_prefix = field_name
while (field_name := f"{field_name_prefix}{counter}") in field_names:
counter += 1
if field_id not in field_names:
break
expressions[field_id] = field
_fields.append(field_id)
else:
_fields.append(field)
if expression is not None:
expressions[field_name] = expression
field_names[field_name] = True
_fields.append(field_name)
clone = self._values(*_fields, **expressions)
clone._iterable_class = (