Search code examples
djangodjango-rest-framework

Django (DRF): How to do case-insensitive ordering


I have an api with ?ordering=name,type

I want both the name and the type to be as case-insensitive

class IngredientListAPIView(ListAPIView):
    queryset = Ingredient.objects.all()
    serializer_class = IngredientListSerializer
    filter_backends = [OrderingFilter]

Solution

  • got the solution from https://github.com/encode/django-rest-framework/issues/3280

    from django.db.models.functions import Lower
    from rest_framework.filters import OrderingFilter
    
    
    class CaseInsensitiveOrderingFilter(OrderingFilter):
    
        def filter_queryset(self, request, queryset, view):
            ordering = self.get_ordering(request, queryset, view)
    
            if ordering:
                new_ordering = []
                for field in ordering:
                    if field.startswith('-'):
                        new_ordering.append(Lower(field[1:]).desc())
                    else:
                        new_ordering.append(Lower(field).asc())
                return queryset.order_by(*new_ordering)
    
            return queryset
    

    then use it in the ListView

    class IngredientListAPIView(ListAPIView):
        queryset = Ingredient.objects.all()
        serializer_class = IngredientListSerializer
        filter_backends = [SearchFilter,CaseInsensitiveOrderingFilter]
        search_fields = ['name','slug']