如何对DRF中的序列化程序自定义字段的值进行排序

时间:2019-07-08 20:20:56

标签: python django django-rest-framework

我已经在客户端序列化程序中创建了一个自定义字段。 此字段的值是通过复杂的序列化器方法计算的。

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):
            ...

我想得到按total_spend_2019的值排序的输出。看起来我无法使用简单的ordering = ('total_spend_2019',)在这里做到这一点,无论在模型中还是在视图中都无法做到。

编辑:拥有可与任何SerializerMethodField一起使用的通用解决方案将是非常棒的。

当前视图如下:

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)

有什么办法解决这个问题吗?

非常感谢您!

2 个答案:

答案 0 :(得分:1)

好的,我设法通过以下方法解决了这个问题:

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)

我不知道这是否是执行此操作最有效的方法,但是它可以工作。

答案 1 :(得分:0)

您还可以尝试创建自定义模型管理器。这是订购数据的普遍决定:

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()
    ...