Anne Sophie
Anne Sophie

Reputation: 130

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!!

Upvotes: 4

Views: 6436

Answers (2)

martbln
martbln

Reputation: 314

Also you can try create your custom model manager. This is popular decision for ordering data:

models.py

class CustomManager(models.Manager):
    def get_queryset(self):
        queryset = super().get_queryset()
        return queryset.filter(...).order_by(...)


class Company(models.Model):
    ...

   objects = models.Manager
   custom_manager = CustomManager()


views.py

class CompanyViewSet(viewsets.ViewSet):
    ...
    queryset = Company.custom_manager.all()
    ...

Upvotes: 2

Anne Sophie
Anne Sophie

Reputation: 130

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.

Upvotes: 7

Related Questions