I use Django for my website and decided to use Django Rest Framework to build my REST API. For a specific model, I want to filter a text field (using SearchFilter for this), filter several categorical fields (FilterBackend of FilterSet is defined), and be able to sort the data based on certain fields (using OrderingFilter for this).
class StatsAPI(generics.ListAPIView): model = Stats queryset = Stats.objects.all() serializer_class = StatsSerializer filter_backends = (filters.DjangoFilterBackend, filters.OrderingFilter, filters.SearchFilter) filter_class = StatsFilter pagination_class = StatsPagination ordering_fields = ('__all__') search_fields = ('display_name')
The problem I am facing is with my ordering fields as they also contain null. Sorting in ascending order works fine. However, sorting in descending order (www.example.com/api/stats/?ordering=-appearance) pushes null values to the top.
How to ignore null values when using descending order? The number of fields on which sorting can be performed is approximately 20.
1> Scott Staffo..:
Here is a slightly different solution – instead of filtering out nulls, replace Dropping filter.OrderingFilter always ensures they are sorted last:
class NullsAlwaysLastOrderingFilter(filters.OrderingFilter): """ Use Django 1.11 nulls_last feature to force nulls to bottom in all orderings. """ def filter_queryset(self, request, queryset, view): ordering = self.get_ordering(request, queryset, view) if ordering: f_ordering = [] for o in ordering: if not o: continue if o[0] == '-': f_ordering.append(F(o[1:]).desc(nulls_last=True)) else: f_ordering.append(F(o).asc(nulls_last=True)) return queryset.order_by(*f_ordering) return queryset