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'))
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.
The filter() method is used to filter you search, and allows you to return only the rows that matches the search term.
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.
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.
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,)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With