Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sort values of serializer custom field in DRF

I have created a custom field in the client serializer. The value of this field is calculated by a complex serializer method.

class ClientsStatsSerializer(serializers.ModelSerializer):
    """
    Serializer shows total_spend for 2019 by client.
    """
    refs_count = serializers.SerializerMethodField()
    total_spend_2019 = serializers.SerializerMethodField()

    class Meta:
        model = Company
        ordering = ('total_spend_2019',)
        fields = [
            'id',
            'legal_name',
            'refs_count',
            'total_spend_2019',
        ]
        def get_total_spend_2019(self, obj):
            ...

I would like to get the output sorted by the value of total_spend_2019. It looks like I cannot do it here with a simple ordering = ('total_spend_2019',) I cannot do it either in the model, neither in the view.

EDIT: It would be great to have a generic solution that would work with any SerializerMethodField.

Current view is as such:

class ClientsStatsViewSet(viewsets.ViewSet):
    def list(self, request):
        queryset = request.user.company.clients.all()

        client_id = self.request.query_params.get('client_id', None)
        if client_id is not None:
            queryset = queryset.filter(pk=client_id)

        serializer = ClientsStatsSerializer(queryset, many=True)
        return Response(serializer.data)

Any idea how to solve this?

Thank you very much!!

like image 313
Anne Sophie Avatar asked Oct 20 '25 16:10

Anne Sophie


1 Answers

All right, I managed to solve it with the following:

class ClientsStatsViewSet(viewsets.ViewSet):
    def list(self, request):
        queryset = request.user.company.clients.all()

        client_id = self.request.query_params.get('client_id', None)
        if client_id is not None:
            queryset = queryset.filter(pk=client_id)

        serializer = ClientsStatsSerializer(queryset, many=True)
        serializer_data = sorted(
            serializer.data, key=lambda k: k['total_spend_2019'], reverse=True)
        return Response(serializer_data)

I don't know if it is the most performant way to do this, but it works.

like image 190
Anne Sophie Avatar answered Oct 23 '25 04:10

Anne Sophie