Reputation: 379
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.
Upvotes: 1
Views: 1203
Reputation: 8026
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)
Upvotes: 1