Skip to content

Commit 2aac176

Browse files
Lotramfelixxm
authored andcommitted
Fixed #31614 -- Fixed aliases ordering by OrderBy() expressions of combined queryset.
1 parent 51ad767 commit 2aac176

File tree

2 files changed

+20
-2
lines changed

2 files changed

+20
-2
lines changed

django/db/models/sql/compiler.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from django.core.exceptions import EmptyResultSet, FieldError
77
from django.db import DatabaseError, NotSupportedError
88
from django.db.models.constants import LOOKUP_SEP
9-
from django.db.models.expressions import OrderBy, Random, RawSQL, Ref, Value
9+
from django.db.models.expressions import F, OrderBy, Random, RawSQL, Ref, Value
1010
from django.db.models.functions import Cast
1111
from django.db.models.query_utils import Q, select_related_descend
1212
from django.db.models.sql.constants import (
@@ -361,13 +361,16 @@ def get_order_by(self):
361361
resolved = expr.resolve_expression(self.query, allow_joins=True, reuse=None)
362362
if self.query.combinator:
363363
src = resolved.get_source_expressions()[0]
364+
expr_src = expr.get_source_expressions()[0]
364365
# Relabel order by columns to raw numbers if this is a combined
365366
# query; necessary since the columns can't be referenced by the
366367
# fully qualified name and the simple column names may collide.
367368
for idx, (sel_expr, _, col_alias) in enumerate(self.select):
368369
if is_ref and col_alias == src.refs:
369370
src = src.source
370-
elif col_alias:
371+
elif col_alias and not (
372+
isinstance(expr_src, F) and col_alias == expr_src.name
373+
):
371374
continue
372375
if src == sel_expr:
373376
resolved.set_source_expressions([RawSQL('%d' % (idx + 1), ())])

tests/queries/test_qs_combinators.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,21 @@ def test_ordering_by_f_expression(self):
123123
qs2 = Number.objects.filter(num__gte=2, num__lte=3)
124124
self.assertNumbersEqual(qs1.union(qs2).order_by(F('num').desc()), [3, 2, 1, 0])
125125

126+
def test_ordering_by_f_expression_and_alias(self):
127+
qs1 = Number.objects.filter(num__lte=1).values(alias=F('other_num'))
128+
qs2 = Number.objects.filter(num__gte=2, num__lte=3).values(alias=F('other_num'))
129+
self.assertQuerysetEqual(
130+
qs1.union(qs2).order_by(F('alias').desc()),
131+
[10, 9, 8, 7],
132+
operator.itemgetter('alias'),
133+
)
134+
Number.objects.create(num=-1)
135+
self.assertQuerysetEqual(
136+
qs1.union(qs2).order_by(F('alias').desc(nulls_last=True)),
137+
[10, 9, 8, 7, None],
138+
operator.itemgetter('alias'),
139+
)
140+
126141
def test_union_with_values(self):
127142
ReservedName.objects.create(name='a', order=2)
128143
qs1 = ReservedName.objects.all()

0 commit comments

Comments
 (0)