Skip to content

Commit ceaf31a

Browse files
committed
Fixed #24420 -- Allowed ordering by case expressions
1 parent 82f7bee commit ceaf31a

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

django/db/models/expressions.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,11 @@ def get_source_expressions(self):
630630
def set_source_expressions(self, exprs):
631631
self.source, = exprs
632632

633+
def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
634+
# The sub-expression `source` has already been resolved, as this is
635+
# just a reference to the name of `source`.
636+
return self
637+
633638
def relabeled_clone(self, relabels):
634639
return self
635640

tests/annotations/tests.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,24 @@ def test_null_annotation(self):
280280
book = Book.objects.annotate(no_value=Value(None, output_field=IntegerField())).first()
281281
self.assertIsNone(book.no_value)
282282

283+
def test_order_by_annotation(self):
284+
authors = Author.objects.annotate(other_age=F('age')).order_by('other_age')
285+
self.assertQuerysetEqual(
286+
authors, [
287+
25, 29, 29, 34, 35, 37, 45, 46, 57,
288+
],
289+
lambda a: a.other_age
290+
)
291+
292+
def test_order_by_aggregate(self):
293+
authors = Author.objects.values('age').annotate(age_count=Count('age')).order_by('age_count', 'age')
294+
self.assertQuerysetEqual(
295+
authors, [
296+
(25, 1), (34, 1), (35, 1), (37, 1), (45, 1), (46, 1), (57, 1), (29, 2),
297+
],
298+
lambda a: (a['age'], a['age_count'])
299+
)
300+
283301
def test_column_field_ordering(self):
284302
"""
285303
Test that columns are aligned in the correct order for

tests/expressions_case/tests.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,30 @@ def test_combined_q_object(self):
980980
transform=attrgetter('integer', 'integer2', 'test')
981981
)
982982

983+
def test_order_by_conditional_implicit(self):
984+
self.assertQuerysetEqual(
985+
CaseTestModel.objects.filter(integer__lte=2).annotate(test=Case(
986+
When(integer=1, then=2),
987+
When(integer=2, then=1),
988+
default=3,
989+
output_field=models.IntegerField(),
990+
)).order_by('test', 'pk'),
991+
[(2, 1), (2, 1), (1, 2)],
992+
transform=attrgetter('integer', 'test')
993+
)
994+
995+
def test_order_by_conditional_explicit(self):
996+
self.assertQuerysetEqual(
997+
CaseTestModel.objects.filter(integer__lte=2).annotate(test=Case(
998+
When(integer=1, then=2),
999+
When(integer=2, then=1),
1000+
default=3,
1001+
output_field=models.IntegerField(),
1002+
)).order_by(F('test').asc(), 'pk'),
1003+
[(2, 1), (2, 1), (1, 2)],
1004+
transform=attrgetter('integer', 'test')
1005+
)
1006+
9831007

9841008
class CaseDocumentationExamples(TestCase):
9851009
@classmethod

0 commit comments

Comments
 (0)