Do case insensitive ordering with a django filter

Is it possible to arrange case-insensitive with first_name using 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 documents for case insensitive search , but nothing for ordering ... p>

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

 >>> from django.db.models.functions import Lower >>> MyModel.objects.order_by(Lower('myfield')) 
+6
source share
4 answers

You might want to subclass OrderingFilter and use it as your filter_backend so you can reuse the code.

 from rest_framework.filters import OrderingFilter from django.db.models.functions import Lower class CaseInsensitiveOrderingFilter(OrderingFilter): def filter_queryset(self, request, queryset, view): ordering = self.get_ordering(request, queryset, view) if ordering is not None: if ordering.startswith('-'): queryset = queryset.order_by(Lower(ordering[1:])).reverse() else: queryset = queryset.order_by(Lower(ordering)) return queryset class PersonViewSet(ModelViewSet): queryset = Person.objects.all() serializer_class = MySerializer permission_classes = (permissions.IsAuthenticated,) filter_backends = (CaseInsensitiveOrderingFilter,) 
+1
source

case-insensitive searches can be performed by overriding the get_queryset method in the ModelViewSet class.

It works for downstream and upstream case-insensitive sequencing.

 # Example URL's '/api/people/?ordering=-first_name' '/api/people/?ordering=first_name' 

Here is the code:

 class PersonViewSet(ModelViewSet): queryset = Person.objects.all() serializer_class = MySerializer permission_classes = (permissions.IsAuthenticated,) def get_queryset(self): queryset = self.queryset ordering = self.request.query_params.get('ordering', None) if ordering is not None: from django.db.models.functions import Lower if ordering.startswith('-'): queryset = queryset.order_by(Lower(ordering[1:])).reverse() else: queryset = queryset.order_by(Lower(ordering)) return queryset 

from django.db.models.functions import Lower only works for the upstream, so call .reverse() on it if you need to go in descending order.

0
source

You can replace the filter OrderingFilter function and set the order parameters to Lower :

 class CaseInsensitiveOrderingFilter(django_filters.OrderingFilter): def filter(self, qs, value): if value in django_filters.constants.EMPTY_VALUES: return qs ordering = [Lower(self.get_ordering_value(param)) for param in value] return qs.order_by(*ordering) 
0
source

use ordering and ordering_fields arguments in your django-rest list view - http://www.django-rest-framework.org/api-guide/filtering/#specifying-a-default-ordering

 class UserListView(generics.ListAPIView): queryset = User.objects.all() serializer_class = UserSerializer filter_backends = (filters.OrderingFilter,) ordering_fields = ('username', 'email') ordering = ('username',) 
-1
source

All Articles