From ceaf31adfff3801f1092a215f73704e15a70e90c Mon Sep 17 00:00:00 2001 From: Josh Smeaton Date: Thu, 5 Mar 2015 17:10:48 +1100 Subject: [PATCH] Fixed #24420 -- Allowed ordering by case expressions --- django/db/models/expressions.py | 5 +++++ tests/annotations/tests.py | 18 ++++++++++++++++++ tests/expressions_case/tests.py | 24 ++++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py index 00a6424886..41ce6ba187 100644 --- a/django/db/models/expressions.py +++ b/django/db/models/expressions.py @@ -630,6 +630,11 @@ class Ref(ExpressionNode): def set_source_expressions(self, exprs): self.source, = exprs + def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False): + # The sub-expression `source` has already been resolved, as this is + # just a reference to the name of `source`. + return self + def relabeled_clone(self, relabels): return self diff --git a/tests/annotations/tests.py b/tests/annotations/tests.py index 2fc42147eb..b5159b6120 100644 --- a/tests/annotations/tests.py +++ b/tests/annotations/tests.py @@ -280,6 +280,24 @@ class NonAggregateAnnotationTestCase(TestCase): book = Book.objects.annotate(no_value=Value(None, output_field=IntegerField())).first() self.assertIsNone(book.no_value) + def test_order_by_annotation(self): + authors = Author.objects.annotate(other_age=F('age')).order_by('other_age') + self.assertQuerysetEqual( + authors, [ + 25, 29, 29, 34, 35, 37, 45, 46, 57, + ], + lambda a: a.other_age + ) + + def test_order_by_aggregate(self): + authors = Author.objects.values('age').annotate(age_count=Count('age')).order_by('age_count', 'age') + self.assertQuerysetEqual( + authors, [ + (25, 1), (34, 1), (35, 1), (37, 1), (45, 1), (46, 1), (57, 1), (29, 2), + ], + lambda a: (a['age'], a['age_count']) + ) + def test_column_field_ordering(self): """ Test that columns are aligned in the correct order for diff --git a/tests/expressions_case/tests.py b/tests/expressions_case/tests.py index 69f47b1d95..42fa8e61a4 100644 --- a/tests/expressions_case/tests.py +++ b/tests/expressions_case/tests.py @@ -980,6 +980,30 @@ class CaseExpressionTests(TestCase): transform=attrgetter('integer', 'integer2', 'test') ) + def test_order_by_conditional_implicit(self): + self.assertQuerysetEqual( + CaseTestModel.objects.filter(integer__lte=2).annotate(test=Case( + When(integer=1, then=2), + When(integer=2, then=1), + default=3, + output_field=models.IntegerField(), + )).order_by('test', 'pk'), + [(2, 1), (2, 1), (1, 2)], + transform=attrgetter('integer', 'test') + ) + + def test_order_by_conditional_explicit(self): + self.assertQuerysetEqual( + CaseTestModel.objects.filter(integer__lte=2).annotate(test=Case( + When(integer=1, then=2), + When(integer=2, then=1), + default=3, + output_field=models.IntegerField(), + )).order_by(F('test').asc(), 'pk'), + [(2, 1), (2, 1), (1, 2)], + transform=attrgetter('integer', 'test') + ) + class CaseDocumentationExamples(TestCase): @classmethod