Trier avec Filters.ordering sur DRF

OrderingFilter permet de filtrer un champs par ordre croissant ou décroissant.

Implémentation

Si cela n'est pas déjà fait, Il faut ajouter le paramètre de filtres dans settings.py : 

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}

 

Dans la view avec les filtres, il suffit d'importer OrderingFilter et de l'ajouter dans le viewset: 

from rest_framework.filters import OrderingFilter

[...] 


class ClassViewSetPublic(viewsets.ReadOnlyModelViewSet):

    filter_backends = [filters.DjangoFilterBackend,
                       DjangoFilterBackend]

    ordering_fields = ['leschampsatrier']

Par contre, cela n'évite pas les null, qui peuvent se retrouver en premier quand on filtre.

Pour éviter cela, nous allons ajouter une classe qui va déplacer les nulls à la fin et modifier le viewset : 

from rest_framework.filters import OrderingFilter

from django.db.models import F





class NullsAlwaysLastOrderingFilter(OrderingFilter):
    def filter_queryset(self, request, queryset, view):
        ordering = self.get_ordering(request, queryset, view)
        if ordering:
            f_ordering = []
            for field in ordering:
                if field.startswith('-'):
                    field_name = field[1:]
                    f_ordering.append(F(field_name).desc(nulls_last=True))
                else:
                    f_ordering.append(F(field).asc(nulls_last=True))
            return queryset.order_by(*f_ordering)
        return queryset



class ClassViewSetPublic(viewsets.ReadOnlyModelViewSet):

    filter_backends = [filters.DjangoFilterBackend,
                       NullsAlwaysLastOrderingFilter]

     #remplacer OrderingFilter par la class

    ordering_fields = ['leschampsatrier']

 

Désormais, les éléments sont triés, et les nulls sont déplacés à la fin.