adds get_ordering method to GenericAPIView

following the pattern of e.g. `django.contrib.admin.ModelAdmin.get_fieldsets`, this PR adds an overrideable accessor to get `viewset.ordering` in order to enable dynamic default orderings. An example of where this is useful is in the case of a SearchFilter which returns results ranked based on similarity, in which case the default ordering should be ignored/bypassed.
This commit is contained in:
Scott Gigante 2023-12-09 13:59:41 -05:00
parent 0f39e0124d
commit 7e71d534e0
3 changed files with 21 additions and 7 deletions

View File

@ -242,10 +242,10 @@ class OrderingFilter(BaseFilterBackend):
return ordering
# No ordering was included, or all the ordering fields were invalid
return self.get_default_ordering(view)
return self.get_default_ordering(request, queryset, view)
def get_default_ordering(self, view):
ordering = getattr(view, 'ordering', None)
def get_default_ordering(self, request, queryset, view):
ordering = view.get_ordering(request, queryset)
if isinstance(ordering, str):
return (ordering,)
return ordering

View File

@ -104,6 +104,15 @@ class GenericAPIView(views.APIView):
return obj
def get_ordering(self, request, queryset):
"""
Returns the default ordering defined on the view.
You may want to override this if you wish the default ordering to be dependent
on the request.
"""
return getattr(self, "ordering", None)
def get_serializer(self, *args, **kwargs):
"""
Return the serializer instance that should be used for validating and

View File

@ -609,6 +609,13 @@ class TestLimitOffset:
}
class GenericOrderedMockView:
filter_backends = (filters.OrderingFilter,)
def get_ordering(self, *args, **kwargs):
return getattr(self, 'ordering', None)
class CursorPaginationTestsMixin:
def test_invalid_cursor(self):
@ -617,8 +624,7 @@ class CursorPaginationTestsMixin:
self.pagination.paginate_queryset(self.queryset, request)
def test_use_with_ordering_filter(self):
class MockView:
filter_backends = (filters.OrderingFilter,)
class MockView(GenericOrderedMockView):
ordering_fields = ['username', 'created']
ordering = 'created'
@ -635,8 +641,7 @@ class CursorPaginationTestsMixin:
assert ordering == ('created',)
def test_use_with_ordering_filter_without_ordering_default_value(self):
class MockView:
filter_backends = (filters.OrderingFilter,)
class MockView(GenericOrderedMockView):
ordering_fields = ['username', 'created']
request = Request(factory.get('/'))