如何在 Django Rest Framework ModelViewSets 中添加聚合值

How to add aggregate values in Django Rest Framework ModelViewSets

在我的 DRF 应用程序中,我有以下模型、序列化程序和视图。

models.py

class Log(models.Model):
    plant = models.ForeignKey(Plant, on_delete=models.CASCADE)
    date_time = models.DateTimeField()
    water_consumption = models.PositiveSmallIntegerField()
    elec_consumption = models.PositiveSmallIntegerField()

serializers.py

class ConsumptionSerializer(serializers.ModelSerializer):
    
    class Meta:
        model = Log
        fields = ("water_consumption", "elec_consumption")

views.py

class ConsumptionViewSet(viewsets.ModelViewSet):
    
    permission_classes = [permissions.IsAuthenticated, ]
    serializer_class = ConsumptionSerializer

    def get_queryset(self):
        # Get params from url
        start_date = self.request.query_params.get('start_date')
        end_date = self.request.query_params.get('end_date')
        # Make sure params are not null
        if start_date is not None and end_date is not None:
            queryset = queryset.filter(date_time__range=[start_date, end_date])
            return queryset
        else:
            raise ValidationError({"ERROR": ["No params found in url"]})
            

这有效,它在 JSON 中输出类似这样的内容:

[
    {
        "water_consumption": 1,
        "electrical_consumption": 1
    },
    {
        "water_consumption": 1,
        "electrical_consumption": 1
    },
    {
        "water_consumption": 1,
        "electrical_consumption": 1
    },
]

我想要实现的是在接收这些数据的同时接收一些聚合数据,如下所示:

{
    "total_water_consumption": 3,
    "total_elec_consumption": 3,
    "detailed_logs": [{
        "water_consumption": 1,
        "electrical_consumption": 1
    },
    {
        "water_consumption": 1,
        "electrical_consumption": 1
    },
    {
        "water_consumption": 1,
        "electrical_consumption": 1
    }]
}

我应该如何自定义查询集以添加总值?

提前致谢。

您可以在序列化程序文件中使用 SerializerMethodField

文档位于:https://www.django-rest-framework.org/api-guide/fields/#serializermethodfield

并且您可以在序列化程序中访问 request 作为 context:

from django.db.models import Sum


class ConsumptionSerializer(serializers.ModelSerializer):
    total_water_consumption = serializers.SerializerMethodField()
    total_elec_consumption = serializers.SerializerMethodField()
    
    class Meta:
        model = Log
        fields = ("water_consumption", "elec_consumption")

    def get_total_water_consumption(self, obj):
        request = self.context['request']
        query_params = request.query_params.get(...)
        return Log.objects.filter(...).aggregate(Sum('water_consumption')).get('water_consumption__sum')

    def get_total_elec_consumption(self, obj):
        request = self.context['request']
        query_params = request.query_params.get(...)
        return Log.objects.filter(...).aggregate(Sum('elec_consumption')).get('elec_consumption__sum')