Skip to content

Commit 0f309c3

Browse files
committed
implement ordering
1 parent 207fcab commit 0f309c3

3 files changed

Lines changed: 61 additions & 3 deletions

File tree

morango/models/core.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,7 @@ class SyncableModel(UUIDModelMixin):
781781

782782
_morango_internal_fields_not_to_serialize = ("_morango_dirty_bit",)
783783
morango_model_dependencies = ()
784+
morango_ordering = ()
784785
morango_fields_not_to_serialize = ()
785786
morango_profile = None
786787

morango/registry.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from collections import OrderedDict
99
from typing import Generator
1010

11-
from django.db.models import QuerySet
11+
from django.db.models import F, QuerySet
1212
from django.db.models.fields.related import ForeignKey
1313

1414
from morango.constants import transfer_stages
@@ -85,7 +85,26 @@ def get_model_querysets(self, profile) -> Generator[QuerySet, None, None]:
8585
(particularly, an order) that is aware of FK dependencies.
8686
"""
8787
for model in self.get_models(profile):
88-
yield model.syncing_objects.all()
88+
queryset = model.syncing_objects.all()
89+
ordering = getattr(model, "morango_ordering", ())
90+
if ordering:
91+
queryset = queryset.order_by(*self._get_nulls_last_ordering(ordering))
92+
yield queryset
93+
94+
@staticmethod
95+
def _get_nulls_last_ordering(ordering):
96+
normalized = []
97+
for order_expr in ordering:
98+
if isinstance(order_expr, str):
99+
descending = order_expr.startswith("-")
100+
field_name = order_expr[1:] if descending else order_expr
101+
if descending:
102+
normalized.append(F(field_name).desc(nulls_last=True))
103+
else:
104+
normalized.append(F(field_name).asc(nulls_last=True))
105+
else:
106+
normalized.append(order_expr)
107+
return normalized
89108

90109
def _insert_model_in_dependency_order(self, model, profile):
91110
# When we add models to be synced, we need to make sure

tests/testapp/tests/integration/test_syncing_models.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import json
22

33
from django.test import TestCase
4-
from facility_profile.models import MyUser, TestModel
4+
from facility_profile.models import Facility, MyUser, TestModel
55

66
from morango.models.core import Store
77
from morango.models.manager import SyncableModelManager
88
from morango.models.query import SyncableModelQuerySet
9+
from morango.registry import syncable_models
910
from morango.sync.controller import MorangoProfileController
1011

1112

@@ -140,3 +141,40 @@ def test_hidden_models_deletion_during_deserialization(self):
140141

141142
# The store record should still exist but marked as deleted
142143
self.assertTrue(Store.objects.filter(id=hidden_obj.id, deleted=True).exists())
144+
145+
def test_get_model_querysets_applies_morango_ordering(self):
146+
old_ordering = Facility.morango_ordering
147+
Facility.morango_ordering = ("-name",)
148+
try:
149+
Facility.objects.create(name="a-facility")
150+
Facility.objects.create(name="z-facility")
151+
queryset = next(
152+
qs
153+
for qs in syncable_models.get_model_querysets(Facility.morango_profile)
154+
if qs.model is Facility
155+
)
156+
self.assertEqual(
157+
list(queryset.values_list("name", flat=True)),
158+
["z-facility", "a-facility"],
159+
)
160+
finally:
161+
Facility.morango_ordering = old_ordering
162+
163+
def test_get_model_querysets_uses_nulls_last_for_string_ordering(self):
164+
old_ordering = Facility.morango_ordering
165+
Facility.morango_ordering = ("parent_id", "name")
166+
try:
167+
root_b = Facility.objects.create(name="root-b", parent=None)
168+
root_a = Facility.objects.create(name="root-a", parent=None)
169+
child = Facility.objects.create(name="child", parent=root_a)
170+
queryset = next(
171+
qs
172+
for qs in syncable_models.get_model_querysets(Facility.morango_profile)
173+
if qs.model is Facility
174+
)
175+
self.assertEqual(
176+
list(queryset.values_list("id", flat=True)),
177+
[child.id, root_a.id, root_b.id],
178+
)
179+
finally:
180+
Facility.morango_ordering = old_ordering

0 commit comments

Comments
 (0)