1

So I currently have a Drink serializer built using django rest framework. It has a field count_need that i obtain using a SerializerMethodField, which is not part of the Drink model. It also has a timestamp field that is part of the model. How can I order the ListAPI view by either timestamp or count_need based on parameters from a get request like /api/drink/?ordering=timestamp. Currently, i have ordering fields specified in the ListAPI view ordering_fields = ('count_need', 'timestamp', ) but it doesnt seem to be ordering the apiview on either query. I can order it by timestamp through the get_queryset method but this doesnt work for count_need because it is not part of the model.

1 Answer 1

1

You could try overriding the get_queryset method on your View and add an annotated field on your queryset for count_need. I think this would be preferable as it may be faster in SQL for large lists, and works with the built-in OrderingFilter of rest framework.

Example:

from django.db.models import Count

class MyView(APIView):
    def get_queryset(self):
        qs = self.queryset
        qs = qs.annotate(count_need=Count('need'))
        return qs

Recommended Reading:
https://docs.djangoproject.com/en/1.11/topics/db/aggregation/#aggregations-and-other-queryset-clauses

The other option is to implement some custom ordering in Python instead of using the Django ORM. You could do this by overriding the list method on your ListAPI view.

def list(self, request, *args, **kwargs):
    queryset = self.filter_queryset(self.get_queryset())

    page = self.paginate_queryset(queryset)
    if page is not None:
        serializer = self.get_serializer(page, many=True)
        serializer_data = serializer.data
        sorted_serializer_data = sorted(serializer_data, key=lambda x: x['count_need'])
        return self.get_paginated_response(sorted_serializer_data)

    serializer = self.get_serializer(queryset, many=True)
    serializer_data = serializer.data
    sorted_serializer_data = sorted(serializer_data, key=lambda x: x['count_need'])
    return Response(sorted_serializer_data)
Sign up to request clarification or add additional context in comments.

1 Comment

Wow the second part of your answer is fantastic, I'll implement it in the morning and comment if it works! Thanks. It looks like it should as far as I can see

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.