Home:ALL Converter>Do case-insensitive ordering with django-filter

Do case-insensitive ordering with django-filter

Ask Time:2015-08-07T01:44:03         Author:Aaron Lelevier

Json Formatter

Is it possible to do case-insensitive ordering by first_name with Django-rest-framework.

Here is the code:

import django_filter

class PersonFilter(django_filters.FilterSet):
    class Meta:
        model = Person
        fields = ('first_name_lower',)
        order_by = ('first_name_lower',)

class PersonViewSet(BaseModelViewSet):
    queryset = Person.objects.all()
    permission_classes = (permissions.IsAuthenticated,)
    filter_backends = (filters.DjangoFilterBackend,)
    filter_class = PersonFilter

Is there an easy way to do case-insensitive ordering with django-filter?

Here django-filter has docs for case-insensitive search, but nothing for ordering.

In the Django docs, the code is somewhat obtuse for this, which makes me wonder if it exists for django-filter or not. Here's the Django docs code snippet on how to do it with the Django ORM:

>>> from django.db.models.functions import Lower
>>> MyModel.objects.order_by(Lower('myfield'))

Author:Aaron Lelevier,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/31862420/do-case-insensitive-ordering-with-django-filter
zemekeneng :

You might want to subclass the OrderingFilter and use it as your filter_backend so that you can reuse the code.\n\nfrom rest_framework.filters import OrderingFilter\nfrom django.db.models.functions import Lower\n\nclass CaseInsensitiveOrderingFilter(OrderingFilter):\n def filter_queryset(self, request, queryset, view):\n ordering = self.get_ordering(request, queryset, view)\n\n if ordering is not None:\n if ordering.startswith('-'):\n queryset = queryset.order_by(Lower(ordering[1:])).reverse()\n else:\n queryset = queryset.order_by(Lower(ordering))\n return queryset\n\n\nclass PersonViewSet(ModelViewSet):\n queryset = Person.objects.all()\n serializer_class = MySerializer\n permission_classes = (permissions.IsAuthenticated,)\n filter_backends = (CaseInsensitiveOrderingFilter,)\n",
2015-11-16T07:19:53
Aaron Lelevier :

The case-insensitive search can be done by overriding the get_queryset method on the ModelViewSet class.\n\nIt works for descending and ascending case-insensitive ordering.\n\n# Example URL's\n'/api/people/?ordering=-first_name'\n'/api/people/?ordering=first_name'\n\n\nHere's the code:\n\nclass PersonViewSet(ModelViewSet):\n queryset = Person.objects.all()\n serializer_class = MySerializer\n permission_classes = (permissions.IsAuthenticated,)\n\n def get_queryset(self):\n queryset = self.queryset\n ordering = self.request.query_params.get('ordering', None)\n if ordering is not None:\n from django.db.models.functions import Lower\n if ordering.startswith('-'):\n queryset = queryset.order_by(Lower(ordering[1:])).reverse()\n else:\n queryset = queryset.order_by(Lower(ordering))\n return queryset\n\n\nfrom django.db.models.functions import Lower only works for Ascending, so basically call .reverse() on it if you need to go Descending.",
2015-08-06T21:53:06
Casper :

You can replace the filter function of OrderingFilter, and set the ordering params in Lower:\n\nclass CaseInsensitiveOrderingFilter(django_filters.OrderingFilter):\n def filter(self, qs, value):\n if value in django_filters.constants.EMPTY_VALUES:\n return qs\n\n ordering = [Lower(self.get_ordering_value(param)) for param in value]\n return qs.order_by(*ordering)\n",
2019-07-25T07:08:40
yy