Skip to content

Commit d2dd7a5

Browse files
committed
allow QuerySet.order_by() to reference annotations
1 parent f11bf9c commit d2dd7a5

File tree

3 files changed

+19
-16
lines changed

3 files changed

+19
-16
lines changed

django_mongodb/compiler.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from django.core.exceptions import EmptyResultSet, FullResultSet
1+
from django.core.exceptions import EmptyResultSet, FieldDoesNotExist, FullResultSet
22
from django.db import DatabaseError, IntegrityError, NotSupportedError
33
from django.db.models import NOT_PROVIDED, Count, Expression
44
from django.db.models.aggregates import Aggregate
@@ -184,7 +184,7 @@ def _get_ordering(self):
184184
if not ordering:
185185
return self.query.standard_ordering
186186

187-
field_ordering = []
187+
column_ordering = []
188188
for order in ordering:
189189
if LOOKUP_SEP in order:
190190
raise NotSupportedError("Ordering can't span tables on MongoDB (%s)." % order)
@@ -199,8 +199,13 @@ def _get_ordering(self):
199199
if name == "pk":
200200
name = opts.pk.name
201201

202-
field_ordering.append((opts.get_field(name), ascending))
203-
return field_ordering
202+
try:
203+
column = opts.get_field(name).column
204+
except FieldDoesNotExist:
205+
# `name` is an annotation in $project.
206+
column = name
207+
column_ordering.append((column, ascending))
208+
return column_ordering
204209

205210
def get_collection(self):
206211
return self.connection.get_collection(self.query.get_meta().db_table)

django_mongodb/features.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
3838
"lookup.tests.LookupQueryingTests.test_lookup_in_order_by",
3939
"ordering.tests.OrderingTests.test_default_ordering_by_f_expression",
4040
"ordering.tests.OrderingTests.test_default_ordering_does_not_affect_group_by",
41+
"ordering.tests.OrderingTests.test_order_by_constant_value",
4142
"ordering.tests.OrderingTests.test_order_by_expression_ref",
4243
"ordering.tests.OrderingTests.test_order_by_f_expression",
4344
"ordering.tests.OrderingTests.test_order_by_f_expression_duplicates",
@@ -61,6 +62,10 @@ class DatabaseFeatures(BaseDatabaseFeatures):
6162
"model_fields.test_jsonfield.TestQuerying.test_order_grouping_custom_decoder",
6263
"model_fields.test_jsonfield.TestQuerying.test_ordering_by_transform",
6364
"model_fields.test_jsonfield.TestQuerying.test_ordering_grouping_by_key_transform",
65+
# alias().order_by() doesn't work.
66+
"annotations.tests.AliasTests.test_order_by_alias",
67+
# annotate() + values_list() + order_by() loses annotated value.
68+
"expressions_case.tests.CaseExpressionTests.test_annotate_values_not_in_order_by",
6469
}
6570
# $bitAnd, #bitOr, and $bitXor are new in MongoDB 6.3.
6671
_django_test_expected_failures_bitwise = {
@@ -221,22 +226,15 @@ def django_test_expected_failures(self):
221226
"annotations.tests.NonAggregateAnnotationTestCase.test_combined_f_expression_annotation_with_aggregation",
222227
"annotations.tests.NonAggregateAnnotationTestCase.test_full_expression_annotation_with_aggregation",
223228
"annotations.tests.NonAggregateAnnotationTestCase.test_grouping_by_q_expression_annotation",
229+
"annotations.tests.NonAggregateAnnotationTestCase.test_order_by_aggregate",
224230
"annotations.tests.NonAggregateAnnotationTestCase.test_q_expression_annotation_with_aggregation",
225231
"expressions_case.tests.CaseDocumentationExamples.test_conditional_aggregation_example",
232+
"model_fields.test_jsonfield.TestQuerying.test_ordering_grouping_by_count",
226233
# Func not implemented.
227234
"annotations.tests.NonAggregateAnnotationTestCase.test_custom_functions",
228235
"annotations.tests.NonAggregateAnnotationTestCase.test_custom_functions_can_ref_other_functions",
229236
# BaseDatabaseOperations may require a format_for_duration_arithmetic().
230237
"annotations.tests.NonAggregateAnnotationTestCase.test_mixed_type_annotation_date_interval",
231-
# FieldDoesNotExist with ordering.
232-
"annotations.tests.AliasTests.test_order_by_alias",
233-
"annotations.tests.NonAggregateAnnotationTestCase.test_order_by_aggregate",
234-
"annotations.tests.NonAggregateAnnotationTestCase.test_order_by_annotation",
235-
"expressions.tests.NegatedExpressionTests.test_filter",
236-
"expressions_case.tests.CaseExpressionTests.test_annotate_values_not_in_order_by",
237-
"expressions_case.tests.CaseExpressionTests.test_order_by_conditional_implicit",
238-
"model_fields.test_jsonfield.TestQuerying.test_ordering_grouping_by_count",
239-
"ordering.tests.OrderingTests.test_order_by_constant_value",
240238
},
241239
"Exists is not supported on MongoDB.": {
242240
"annotations.tests.NonAggregateAnnotationTestCase.test_annotation_exists_none_query",

django_mongodb/query.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def order_by(self, ordering):
6464
Reorder query results or execution order. Called by compiler during
6565
query building.
6666
67-
`ordering` is a list with (field, ascending) tuples or a boolean --
67+
`ordering` is a list with (column, ascending) tuples or a boolean --
6868
use natural ordering, if any, when the argument is True and its reverse
6969
otherwise.
7070
"""
@@ -73,9 +73,9 @@ def order_by(self, ordering):
7373
if not ordering:
7474
self.ordering.append(("$natural", DESCENDING))
7575
else:
76-
for field, ascending in ordering:
76+
for column, ascending in ordering:
7777
direction = ASCENDING if ascending else DESCENDING
78-
self.ordering.append((field.column, direction))
78+
self.ordering.append((column, direction))
7979

8080
@wrap_database_errors
8181
def delete(self):

0 commit comments

Comments
 (0)