Trier avec Filters.ordering sur DRF
Le 06 février 2024 | Django
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.