2015-08-06 19 views
6

E 'possibile fare case-insensitive ordinando per first_name con Django-rest-framework.Do order-insensitive order with django-filter

Ecco il codice:

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 

C'è un modo semplice per farlo case-insensitive ordinazione con django-filter?

Here django-filtro ha docs per case-insensitive ricerca, ma nulla per ordinare.

Nei documenti Django, il codice è in qualche modo ottuso per questo, il che mi fa pensare se esiste per django-filter oppure no. Ecco il codice docs Django frammento su come farlo con il Django ORM:

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

risposta

-1

utilizzare gli argomenti di ordinazione e ordering_fields nel vostro django-riposo visualizzazione elenco - 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', ecc ... funziona per l'ordine, ma * non fa distinzione tra maiuscole e minuscole *. Django ORM è 'case-sensitive' di default, e l'argomento' ordering_fields' sopra usa la funzionalità predefinita di Django ORM per 'model.objects.order_by'. –

0

La ricerca case-insensitive può essere fatto ignorando il metodo get_queryset nella classe ModelViewSet.

Funziona per decrescente e ascendentecase-insensitive ordinazione.

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

Ecco il codice:

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 funziona solo per Crescente, in modo sostanzialmente chiamare .reverse() su di esso, se avete bisogno di andare Discendente.

+0

Solo una breve nota sulla tua ultima frase, puoi effettivamente eseguire 'Lower (ordering) .asc() o Lower (ordering) .desc()' che consentirebbe di mescolare ascendente e discendente in combinazione con Lower su diversi campi. –

0

È possibile creare sottoclasse di OrderingFilter e utilizzarlo come filter_backend in modo da poter riutilizzare il codice.

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

Questa soluzione funzionerà, ma solo con un singolo argomento 'ordering'. –