2015-08-06 9 views
6

Ist es möglich, case-insensitive zu bestellen, indem Sie first_name mit Django-rest-framework. HierIst die Groß- und Kleinschreibung nicht zu beachten?

ist der 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 

Gibt es eine einfache Möglichkeit, case-insensitive Bestellung mit django-filter zu tun?

Here django-Filter hat docs für Groß- und Kleinschreibung Suche, aber nichts für Bestellung.

In den Django-Dokumenten ist der Code dafür etwas stumpf, was mich fragt, ob er für django-filter existiert oder nicht. Hier ist die Django docs Code-Schnipsel, wie es mit dem Django ORM zu tun:

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

Antwort

-1

verwenden, um die Bestellung und ordering_fields Argumente in Ihrer django-Rest Listenansicht - 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 ... funktioniert für die Bestellung, aber es ist * nicht case-insensitive *. Das Django-ORM ist standardmäßig "case-sensitive", und das obige 'ordering_fields'-Argument verwendet die Standard-Django-ORM-Funktionalität für' model.objects.order_by'. –

0

Die case-insensitive Suche sein kann getan durch Überschreiben der get_queryset Methode auf der ModelViewSet Klasse.

Es funktioniert für absteigend und case-insensitive Reihenfolge aufsteigend.

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

Hier ist der 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 funktioniert nur für aufsteigende, so wenden grundsätzlich .reverse() auf es, wenn Sie absteigend gehen müssen.

+0

Nur eine kurze Notiz über Ihren letzten Satz, Sie können tatsächlich tun 'Lower (Reihenfolge) .asc() oder Lower (Reihenfolge) .desc()', die auf verschiedenen Feldern aufsteigend und absteigend in Kombination mit Lower mischen könnte. –

0

Sie könnten die OrderingFilter unterklassifizieren und sie als filter_backend verwenden, damit Sie den Code wiederverwenden können.

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

Diese Lösung funktioniert, aber nur mit einem einzelnen 'ordering'-Argument. –

Verwandte Themen