如何在 Django Rest Framework ModelViewSets 中添加聚合值
Posted
技术标签:
【中文标题】如何在 Django Rest Framework ModelViewSets 中添加聚合值【英文标题】:How to add aggregate values in Django Rest Framework ModelViewSets 【发布时间】:2021-12-07 00:05:07 【问题描述】:在我的 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()
序列化器.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
]
我应该如何自定义查询集以添加总值?
提前谢谢你。
【问题讨论】:
【参考方案1】:您可以在序列化程序文件中使用SerializerMethodField
来完成
文档在:https://www.django-rest-framework.org/api-guide/fields/#serializermethodfield
您可以在序列化程序中以context
访问request
:
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')
【讨论】:
你好@Amin,我试过了,但没有成功,因为过滤器依赖于每次请求时从 url 获取的参数,那么如何将这些传递给序列化程序? 我已经为你更新了答案@Giulia 非常感谢,这很有意义,我得到了它的工作。只是,这样它在所有日志中添加了聚合字段,是否可以在响应中只添加一次,然后是日志? 您可以为此使用嵌套序列化程序。有一个包含这两个聚合字段的序列化程序,以及一个名为logs
的字段,例如,它与您之前的序列化程序嵌套。然后将您的项目作为 logs
关键字传递给序列化程序... @Giulia
或者你可以在你的序列化器中覆盖to_represention()
方法。或者将这些汇总字段附加到您之前的最终结果views
@Giulia以上是关于如何在 Django Rest Framework ModelViewSets 中添加聚合值的主要内容,如果未能解决你的问题,请参考以下文章
Django.rest_framework:如何序列化一对多?
如何使用 TemplateHTMLRenderer 在 Django-REST-Framework 中创建/放置?
django-rest-framework:如何序列化已经包含 JSON 的字段?
如何在 Django Rest Framework 中散列 Django 用户密码?