Source code for rest_framework_tricks.filters.ordering

"""
Ordering filter.
"""
from rest_framework.filters import OrderingFilter as DjangoOrderingFilter

__author__ = "Artur Barseghyan <artur.barseghyan@gmail.com>"
__copyright__ = "2017-2022 Artur Barseghyan"
__license__ = "GPL-2.0-only OR LGPL-2.1-or-later"
__all__ = ("OrderingFilter",)


[docs]class OrderingFilter(DjangoOrderingFilter): """Ordering filter improved. Example: >>> from rest_framework_tricks.filters import OrderingFilter >>> >>> class BooksViewSet(mixins.RetrieveModelMixin, >>> mixins.ListModelMixin, >>> viewsets.GenericViewSet): >>> >>> serializer_class = BookSerializer >>> filter_backends = ( >>> OrderingFilter, >>> ) >>> ordering_fields = { >>> 'email': 'user__email', >>> 'full_name': 'user__first_name', >>> 'last_login': 'user__last_login', >>> 'is_active': 'user__is_active', >>> } Then it can be used in a view set as follows: GET /books/api/proxy-books/?ordering=email """
[docs] def get_valid_fields(self, queryset, view, context=None): """Done. :param queryset: :param view: :param context: :return: """ valid_fields = getattr(view, "ordering_fields", self.ordering_fields) if context is None: context = {} if isinstance(valid_fields, dict): return valid_fields.items() else: return super(OrderingFilter, self).get_valid_fields( queryset, view, context )
[docs] def get_ordering(self, request, queryset, view): """Get ordering. Important: list returned in this method is used directly in the filter_queryset method like: >>> queryset.order_by(*ordering) Ordering is set by a comma delimited ?ordering=... query parameter. The `ordering` query parameter can be overridden by setting the `ordering_param` value on the OrderingFilter or by specifying an `ORDERING_PARAM` value in the API settings. """ valid_fields = getattr(view, "ordering_fields", self.ordering_fields) # If valid_fields is a dictionary, treat it differently if isinstance(valid_fields, dict): params = request.query_params.get(self.ordering_param) if params: fields = [param.strip() for param in params.split(",")] _ordering = self.remove_invalid_fields( queryset, fields, view, request ) ordering = [] for item in _ordering: if "-" in item: value = valid_fields.get(item[1:]) if isinstance(value, (tuple, list)): value = ["-{}".format(__v) for __v in value] ordering += value else: ordering.append("-{}".format(value)) else: value = valid_fields.get(item) if isinstance(value, (tuple, list)): ordering += value else: ordering.append(value) if ordering: return ordering # No ordering was included, or all the ordering fields were invalid return self.get_default_ordering(view) # In all other cases, use default behaviour else: return super(OrderingFilter, self).get_ordering( request, queryset, view )