Django Rest Ordering custom

Issue

I’m using django rest framework and I would like to order with a custom method.

So, when I call this url for example : http://127.0.0.1:8000/api/sets/?ordering=partMissing

It’s possible to call a custom method because I would like to order with the number of part missing by snippet. I made count the sum of number of part in the many to many field.

Solution

I have very simple POC, that should allow you to implement more sophisticated solution.

views.py:

from rest_framework import viewsets

from ordering_test.models import Test
from ordering_test.ordering import MyCustomOrdering
from ordering_test.serializers import TestSerializer

class TestViewSet(viewsets.ModelViewSet):
    queryset = Test.objects.all()
    serializer_class = TestSerializer
    filter_backends = (MyCustomOrdering,)

ordering.py:

from rest_framework.filters import OrderingFilter

class MyCustomOrdering(OrderingFilter):

    allowed_custom_filters = ['testMethod']

    def get_ordering(self, request, queryset, view):
        """
        Ordering is set by a comma delimited ?ordering=... query parameter.

        The `ordering` query parameter can be overridden by setting
        the `ordering_param` value on the OrderingFilter or by
        specifying an `ORDERING_PARAM` value in the API settings.
        """
        params = request.query_params.get(self.ordering_param)

        if params:
            fields = [param.strip() for param in params.split(',')]
            # care with that - this will alow only custom ordering!
            ordering = [f for f in fields if f in self.allowed_custom_filters]
            if ordering:
                return ordering

        # No ordering was included, or all the ordering fields were invalid
        return self.get_default_ordering(view)

    def filter_queryset(self, request, queryset, view):

        ordering = self.get_ordering(request, queryset, view)
        if ordering:
            # implement a custom ordering here
            ordering = ['-id']

        if ordering:
            return queryset.order_by(*ordering)

        return queryset

The models.py and serializers.py are straightforward, but I will still include them here:

models.py:

from django.db import models

class Test(models.Model):
    test = models.CharField(max_length=120)
    test1 = models.CharField(max_length=120)

serializers.py:

from rest_framework import serializers

from ordering_test.models import Test

class TestSerializer(serializers.ModelSerializer):

    class Meta:
        model = Test
        fields = ('test', 'test1')

Happy coding!

Answered By – opalczynski

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published