2015-08-06 3 views
6

Можно ли сделать case-insensitive заказать по first_name с Django-rest-framework.Нечувствительный к регистру заказ с django-фильтром

Вот код:

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 

Есть простой способ сделать case-insensitive заказ с django-filter?

Here Джанго-фильтр имеет документы для учета регистра поиска, но ничего для заказа.

В документах Django код несколько тупой для этого, что заставляет меня задаться вопросом, существует ли он для django-filter или нет. Вот Django документы фрагмент кода о том, как это сделать с Django ORM:

>>> from django.db.models.functions import Lower 
>>> MyModel.objects.order_by(Lower('myfield')) 

ответ

-1

использовать аргументы упорядочения и 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',) 
+2

'ordering_fields', etc ... работает для заказа, но это * не учитывает регистр *. Django ORM по умолчанию чувствителен к регистру, а аргумент 'ordering_fields' выше использует функциональность Django ORM по умолчанию для' model.objects.order_by'. –

0

case-insensitive поиск может быть сделанное путем переопределения метода get_queryset класса ModelViewSet.

Он работает для убыванию и возрастаниюcase-insensitive упорядоченность.

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

Вот код:

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 работает только для восходящих, так что в основном называют .reverse() на него, если вам нужно пойти Убывание.

+0

Просто короткое замечание о последнем предложении, вы можете на самом деле сделать «Lower (ordering) .asc() или Lower (ordering) .desc()», что позволило бы смешивать восходящий и нисходящий в сочетании с Lower в разных полях. –

0

Возможно, вы захотите подклассифицировать 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,) 
+0

Это решение будет работать, но только с одним аргументом 'ordering'. –

Смежные вопросы