Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do case-insensitive ordering with django-filter

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'))
like image 831
Aaron Lelevier Avatar asked Aug 06 '15 17:08

Aaron Lelevier


People also ask

Is Django case sensitive?

So, the programmer has told Django explicitly, 'I want case-insensitive comparison', and Django tells MySQL, 'We want default comparison'. This is not field_icontains but rather some field_usingdefaultsettingscontains. So, case-sensitivity is explicitly requested, while case-insensitivity is implied.

What is the purpose of filter () method in Django?

The filter() method is used to filter you search, and allows you to return only the rows that matches the search term.

What is the difference between GET and filter in Django?

Returns a new QuerySet containing objects that match the given lookup parameters. Basically use get() when you want to get a single unique object, and filter() when you want to get all objects that match your lookup parameters.

What does Django filter return?

Django provides a filter() method which returns a subset of data. It accepts field names as keyword arguments and returns a QuerySet object. As database has only one record where name is 'tom' , the QuerySet object contains only a single record.


1 Answers

You might want to subclass the OrderingFilter and use it as your filter_backend so that 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,)
like image 107
zemekeneng Avatar answered Sep 16 '22 13:09

zemekeneng