Skip to content

Commit e347d97

Browse files
committed
allow QuerySet.order_by() to reference annotations
1 parent b03ec92 commit e347d97

File tree

3 files changed

+21
-18
lines changed

3 files changed

+21
-18
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
@@ -212,7 +212,7 @@ def _get_ordering(self):
212212
if not ordering:
213213
return self.query.standard_ordering
214214

215-
field_ordering = []
215+
column_ordering = []
216216
for order in ordering:
217217
if LOOKUP_SEP in order:
218218
raise NotSupportedError("Ordering can't span tables on MongoDB (%s)." % order)
@@ -227,8 +227,13 @@ def _get_ordering(self):
227227
if name == "pk":
228228
name = opts.pk.name
229229

230-
field_ordering.append((opts.get_field(name), ascending))
231-
return field_ordering
230+
try:
231+
column = opts.get_field(name).column
232+
except FieldDoesNotExist:
233+
# `name` is an annotation in $project.
234+
column = name
235+
column_ordering.append((column, ascending))
236+
return column_ordering
232237

233238
@cached_property
234239
def collection_name(self):

django_mongodb/features.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
4040
"ordering.tests.OrderingTests.test_default_ordering",
4141
"ordering.tests.OrderingTests.test_default_ordering_by_f_expression",
4242
"ordering.tests.OrderingTests.test_default_ordering_does_not_affect_group_by",
43+
"ordering.tests.OrderingTests.test_order_by_constant_value",
4344
"ordering.tests.OrderingTests.test_order_by_expr_query_reuse",
4445
"ordering.tests.OrderingTests.test_order_by_expression_ref",
4546
"ordering.tests.OrderingTests.test_order_by_f_expression",
@@ -87,7 +88,9 @@ class DatabaseFeatures(BaseDatabaseFeatures):
8788
# Wrong results in queries with multiple tables.
8889
"annotations.tests.NonAggregateAnnotationTestCase.test_annotation_aggregate_with_m2o",
8990
"annotations.tests.NonAggregateAnnotationTestCase.test_annotation_reverse_m2m",
91+
"annotations.tests.NonAggregateAnnotationTestCase.test_annotation_with_m2m",
9092
"annotations.tests.NonAggregateAnnotationTestCase.test_chaining_annotation_filter_with_m2m",
93+
"annotations.tests.NonAggregateAnnotationTestCase.test_mti_annotations",
9194
"lookup.tests.LookupTests.test_lookup_collision",
9295
"expressions.test_queryset_values.ValuesExpressionsTests.test_values_list_expression",
9396
"expressions.test_queryset_values.ValuesExpressionsTests.test_values_list_expression_flat",
@@ -102,6 +105,10 @@ class DatabaseFeatures(BaseDatabaseFeatures):
102105
# pymongo.errors.OperationFailure: $multiply only supports numeric
103106
# types, not date. (should be wrapped in DatabaseError).
104107
"expressions.tests.FTimeDeltaTests.test_invalid_operator",
108+
# alias().order_by() doesn't work.
109+
"annotations.tests.AliasTests.test_order_by_alias",
110+
# annotate() + values_list() + order_by() loses annotated value.
111+
"expressions_case.tests.CaseExpressionTests.test_annotate_values_not_in_order_by",
105112
}
106113
# $bitAnd, #bitOr, and $bitXor are new in MongoDB 6.3.
107114
_django_test_expected_failures_bitwise = {
@@ -280,27 +287,18 @@ def django_test_expected_failures(self):
280287
"annotations.tests.NonAggregateAnnotationTestCase.test_combined_f_expression_annotation_with_aggregation",
281288
"annotations.tests.NonAggregateAnnotationTestCase.test_full_expression_annotation_with_aggregation",
282289
"annotations.tests.NonAggregateAnnotationTestCase.test_grouping_by_q_expression_annotation",
290+
"annotations.tests.NonAggregateAnnotationTestCase.test_order_by_aggregate",
283291
"annotations.tests.NonAggregateAnnotationTestCase.test_q_expression_annotation_with_aggregation",
284292
"defer_regress.tests.DeferRegressionTest.test_basic",
285293
"defer_regress.tests.DeferRegressionTest.test_defer_annotate_select_related",
286294
"defer_regress.tests.DeferRegressionTest.test_ticket_16409",
287295
"expressions.tests.BasicExpressionsTests.test_aggregate_subquery_annotation",
288296
"expressions.tests.FieldTransformTests.test_month_aggregation",
289297
"expressions_case.tests.CaseDocumentationExamples.test_conditional_aggregation_example",
298+
"model_fields.test_jsonfield.TestQuerying.test_ordering_grouping_by_count",
290299
# Func not implemented.
291300
"annotations.tests.NonAggregateAnnotationTestCase.test_custom_functions",
292301
"annotations.tests.NonAggregateAnnotationTestCase.test_custom_functions_can_ref_other_functions",
293-
# FieldDoesNotExist with ordering.
294-
"annotations.tests.AliasTests.test_order_by_alias",
295-
"annotations.tests.NonAggregateAnnotationTestCase.test_annotation_with_m2m",
296-
"annotations.tests.NonAggregateAnnotationTestCase.test_mti_annotations",
297-
"annotations.tests.NonAggregateAnnotationTestCase.test_order_by_aggregate",
298-
"annotations.tests.NonAggregateAnnotationTestCase.test_order_by_annotation",
299-
"expressions.tests.NegatedExpressionTests.test_filter",
300-
"expressions_case.tests.CaseExpressionTests.test_annotate_values_not_in_order_by",
301-
"expressions_case.tests.CaseExpressionTests.test_order_by_conditional_implicit",
302-
"model_fields.test_jsonfield.TestQuerying.test_ordering_grouping_by_count",
303-
"ordering.tests.OrderingTests.test_order_by_constant_value",
304302
},
305303
"Exists is not supported on MongoDB.": {
306304
"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
@@ -72,7 +72,7 @@ def order_by(self, ordering):
7272
Reorder query results or execution order. Called by compiler during
7373
query building.
7474
75-
`ordering` is a list with (field, ascending) tuples or a boolean --
75+
`ordering` is a list with (column, ascending) tuples or a boolean --
7676
use natural ordering, if any, when the argument is True and its reverse
7777
otherwise.
7878
"""
@@ -81,9 +81,9 @@ def order_by(self, ordering):
8181
if not ordering:
8282
self.ordering.append(("$natural", DESCENDING))
8383
else:
84-
for field, ascending in ordering:
84+
for column, ascending in ordering:
8585
direction = ASCENDING if ascending else DESCENDING
86-
self.ordering.append((field.column, direction))
86+
self.ordering.append((column, direction))
8787

8888
@wrap_database_errors
8989
def delete(self):

0 commit comments

Comments
 (0)