[英]Do case-insensitive ordering with django-filter
Is it possible to do case-insensitive
ordering by first_name
with Django-rest-framework . 是否可以通过
first_name
与Django-rest-framework case-insensitive
排序。
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
? 是否有一种简单的方法可以使用
django-filter
case-insensitive
排序?
Here django-filter has docs for case-insensitive search , but nothing for ordering . 这里 django-filter有不区分大小写搜索的文档,但没有用于排序 。
In the Django docs, the code is somewhat obtuse for this, which makes me wonder if it exists for django-filter
or not. 在Django文档中,代码对此有点迟钝,这让我想知道是否存在
django-filter
。 Here's the Django docs code snippet on how to do it with the Django ORM: 这里是关于如何使用Django ORM的Django文档代码片段:
>>> from django.db.models.functions import Lower
>>> MyModel.objects.order_by(Lower('myfield'))
You might want to subclass the OrderingFilter
and use it as your filter_backend
so that you can reuse the code. 您可能希望将
OrderingFilter
子类化并将其用作filter_backend
以便您可以重用代码。
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,)
The case-insensitive
search can be done by overriding the get_queryset
method on the ModelViewSet
class. 在
case-insensitive
搜索可以通过重写来完成get_queryset
的方法ModelViewSet
类。
It works for descending and ascending case-insensitive
ordering. 它适用于降序和升序
case-insensitive
顺序。
# Example URL's
'/api/people/?ordering=-first_name'
'/api/people/?ordering=first_name'
Here's 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 Ascending, so basically call .reverse()
on it if you need to go Descending. from django.db.models.functions import Lower
只适用于升序,所以如果需要降序,基本上可以调用.reverse()
。
You can replace the filter
function of OrderingFilter
, and set the ordering params in Lower
: 您可以替换
OrderingFilter
的filter
函数,并在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)
use the ordering and ordering_fields arguments in your django-rest list view - http://www.django-rest-framework.org/api-guide/filtering/#specifying-a-default-ordering 使用django-rest列表视图中的ordering和ordering_fields参数 - 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',)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.