mirror of
https://github.com/django/django.git
synced 2024-12-23 01:25:58 +00:00
Demonstrate how implicit ordering of extra(select) can be preserved.
This commit is contained in:
parent
9a83c66561
commit
ed6788bbd7
@ -210,9 +210,19 @@ class ValuesIterable(BaseIterable):
|
|||||||
if query.selected:
|
if query.selected:
|
||||||
names = list(query.selected)
|
names = list(query.selected)
|
||||||
else:
|
else:
|
||||||
|
# RemovedInDjango60Warning: place extra(select) entries at the
|
||||||
|
# beginning of the SELECT clause until it's completely removed.
|
||||||
|
extra_names = []
|
||||||
|
annotation_select = []
|
||||||
|
for alias, expression in query.annotation_select.items():
|
||||||
|
if isinstance(expression, _ExtraSelectFirstRawSQL):
|
||||||
|
extra_names.append(alias)
|
||||||
|
else:
|
||||||
|
annotation_select.append(alias)
|
||||||
names = [
|
names = [
|
||||||
|
*extra_names,
|
||||||
*query.values_select,
|
*query.values_select,
|
||||||
*query.annotation_select,
|
*annotation_select,
|
||||||
]
|
]
|
||||||
indexes = range(len(names))
|
indexes = range(len(names))
|
||||||
for row in compiler.results_iter(
|
for row in compiler.results_iter(
|
||||||
@ -250,9 +260,19 @@ class NamedValuesListIterable(ValuesListIterable):
|
|||||||
names = queryset._fields
|
names = queryset._fields
|
||||||
else:
|
else:
|
||||||
query = queryset.query
|
query = queryset.query
|
||||||
|
# RemovedInDjango60Warning: place extra(select) entries at the
|
||||||
|
# beginning of the SELECT clause until it's completely removed.
|
||||||
|
extra_names = []
|
||||||
|
annotation_select = []
|
||||||
|
for alias, expression in query.annotation_select.items():
|
||||||
|
if isinstance(expression, _ExtraSelectFirstRawSQL):
|
||||||
|
extra_names.append(alias)
|
||||||
|
else:
|
||||||
|
annotation_select.append(alias)
|
||||||
names = [
|
names = [
|
||||||
|
*extra_names,
|
||||||
*query.values_select,
|
*query.values_select,
|
||||||
*query.annotation_select,
|
*annotation_select,
|
||||||
]
|
]
|
||||||
tuple_class = create_namedtuple_class(*names)
|
tuple_class = create_namedtuple_class(*names)
|
||||||
new = tuple.__new__
|
new = tuple.__new__
|
||||||
@ -275,6 +295,17 @@ class FlatValuesListIterable(BaseIterable):
|
|||||||
yield row[0]
|
yield row[0]
|
||||||
|
|
||||||
|
|
||||||
|
# RemovedInDjango60Warning
|
||||||
|
class _ExtraSelectFirstRawSQL(RawSQL):
|
||||||
|
"""
|
||||||
|
Internal RawSQL subclass used during the deprecation of extra(select) to
|
||||||
|
preserve the undocumented implicit ordering of members at the begining of
|
||||||
|
the SELECT clause.
|
||||||
|
"""
|
||||||
|
|
||||||
|
implicitly_select_first = True
|
||||||
|
|
||||||
|
|
||||||
class QuerySet(AltersData):
|
class QuerySet(AltersData):
|
||||||
"""Represent a lazy database lookup for a set of objects."""
|
"""Represent a lazy database lookup for a set of objects."""
|
||||||
|
|
||||||
@ -1724,8 +1755,6 @@ class QuerySet(AltersData):
|
|||||||
category=RemovedInDjango60Warning,
|
category=RemovedInDjango60Warning,
|
||||||
stacklevel=2,
|
stacklevel=2,
|
||||||
)
|
)
|
||||||
# XXX: This is mising the logic to always place extras at the begining
|
|
||||||
# of the select clause.
|
|
||||||
if select_params:
|
if select_params:
|
||||||
param_iter = iter(select_params)
|
param_iter = iter(select_params)
|
||||||
else:
|
else:
|
||||||
@ -1739,7 +1768,9 @@ class QuerySet(AltersData):
|
|||||||
if pos == 0 or entry[pos - 1] != "%":
|
if pos == 0 or entry[pos - 1] != "%":
|
||||||
entry_params.append(next(param_iter))
|
entry_params.append(next(param_iter))
|
||||||
pos = entry.find("%s", pos + 2)
|
pos = entry.find("%s", pos + 2)
|
||||||
clone.query.add_annotation(RawSQL(entry, entry_params), name)
|
clone.query.add_annotation(
|
||||||
|
_ExtraSelectFirstRawSQL(entry, entry_params), name
|
||||||
|
)
|
||||||
if where:
|
if where:
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"extra(where) usage is deprecated, use filter() with RawSQL instead.",
|
"extra(where) usage is deprecated, use filter() with RawSQL instead.",
|
||||||
|
@ -262,9 +262,22 @@ class SQLCompiler:
|
|||||||
}
|
}
|
||||||
selected = []
|
selected = []
|
||||||
if self.query.selected is None:
|
if self.query.selected is None:
|
||||||
|
# RemovedInDjango60Warning: place extra(select) entries at the
|
||||||
|
# beginning of the SELECT clause until it's completely removed.
|
||||||
|
leading_annotation_select = []
|
||||||
|
annotation_select = []
|
||||||
|
if self.query.values_select_all:
|
||||||
|
for alias, expression in self.query.annotation_select.items():
|
||||||
|
if getattr(expression, "implicitly_select_first", False):
|
||||||
|
leading_annotation_select.append((alias, expression))
|
||||||
|
else:
|
||||||
|
annotation_select.append((alias, expression))
|
||||||
|
else:
|
||||||
|
annotation_select = self.query.annotation_select.items()
|
||||||
selected = [
|
selected = [
|
||||||
|
*leading_annotation_select,
|
||||||
*((None, col) for col in cols),
|
*((None, col) for col in cols),
|
||||||
*self.query.annotation_select.items(),
|
*annotation_select,
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
for alias, expression in self.query.selected.items():
|
for alias, expression in self.query.selected.items():
|
||||||
|
@ -286,7 +286,7 @@ class ExtraRegressTests(TestCase):
|
|||||||
select={"foo": "first", "bar": "second", "whiz": "third"}
|
select={"foo": "first", "bar": "second", "whiz": "third"}
|
||||||
).values_list()
|
).values_list()
|
||||||
),
|
),
|
||||||
[(obj.pk, "first", "second", "third", "first", "second", "third")],
|
[("first", "second", "third", obj.pk, "first", "second", "third")],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Extra columns after an empty values_list() are still included
|
# Extra columns after an empty values_list() are still included
|
||||||
@ -296,7 +296,7 @@ class ExtraRegressTests(TestCase):
|
|||||||
select={"foo": "first", "bar": "second", "whiz": "third"}
|
select={"foo": "first", "bar": "second", "whiz": "third"}
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
[(obj.pk, "first", "second", "third", "first", "second", "third")],
|
[("first", "second", "third", obj.pk, "first", "second", "third")],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Extra columns ignored completely if not mentioned in values_list()
|
# Extra columns ignored completely if not mentioned in values_list()
|
||||||
|
@ -2841,7 +2841,7 @@ class ValuesQuerysetTests(TestCase):
|
|||||||
self.assertEqual(type(values).__name__, "Row")
|
self.assertEqual(type(values).__name__, "Row")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
values._fields,
|
values._fields,
|
||||||
("id", "num", "other_num", "another_num", "num2", "id__count"),
|
("num2", "id", "num", "other_num", "another_num", "id__count"),
|
||||||
)
|
)
|
||||||
self.assertEqual(values.num, 72)
|
self.assertEqual(values.num, 72)
|
||||||
self.assertEqual(values.num2, 73)
|
self.assertEqual(values.num2, 73)
|
||||||
|
Loading…
Reference in New Issue
Block a user