如何在Django Rest Framework序列化器中统计在线Plant数量?
在Django Rest Framework序列化器中实现关联Plant在线数量统计
核心解决方案思路
通过Django ORM的annotate和Count结合过滤条件,在数据库层面完成在线Plant的统计,避免序列化器中额外的数据库查询,提升效率。同时调整序列化器和视图的关联模型,匹配统计需求。
修正后的代码实现
1. 导入必要模块
from django.db.models import Count, Q from rest_framework import generics from rest_framework.permissions import AllowAny from .models import PVOwner, TablePlants, TableSitePlant from .serializers import OverviewPlantsActiveSerializer
2. 序列化器定义
基于PVOwner模型创建序列化器,直接映射ORM注解生成的plants_active统计字段:
class OverviewPlantsActiveSerializer(serializers.ModelSerializer): # read_only=True 因为字段由ORM注解生成,无需前端传入 plants_active = serializers.IntegerField(read_only=True) class Meta: model = PVOwner # 可根据需求添加PVOwner的其他字段 fields = ['pv_owner_id', 'plants_active']
3. 视图实现
通过annotate为每个PVOwner统计关联的在线Plant数量,使用RetrieveAPIView获取单个所有者的统计数据:
@permission_classes([AllowAny]) class OverviewPlantsActiveView(generics.RetrieveAPIView): # 注解查询:统计当前PVOwner下关联的plant_status为online的Plant数量 queryset = PVOwner.objects.annotate( plants_active=Count( 'pv_site_owner_plant__plant', # 过滤条件:仅统计状态为online的Plant filter=Q(pv_site_owner_plant__plant__plant_status='online'), # distinct=True 避免重复统计同一个Plant(如果存在重复关联) distinct=True ) ) serializer_class = OverviewPlantsActiveSerializer # 基于PVOwner的主键作为查询字段,可根据实际需求调整 lookup_field = 'pv_owner_id'
对原有代码问题的说明
- 原有序列化器中
source="plant"错误:plant是外键对象,无法直接转为整数类型的统计值 - 视图查询集过滤条件错误:原代码过滤的是
offline状态,与需求的在线统计不符 - 模型关联逻辑不匹配:统计应基于
PVOwner而非TableSitePlant,因为一个PVOwner对应多个Plant关联记录 - 序列化器名称不匹配:原视图引用
OverviewPlantsActiveSerializer但定义的是MainMenuSerializer
可选:批量统计所有PVOwner的在线Plant数量
如果需要返回所有所有者的统计数据,将视图改为ListAPIView即可:
@permission_classes([AllowAny]) class OverviewPlantsActiveListView(generics.ListAPIView): queryset = PVOwner.objects.annotate( plants_active=Count( 'pv_site_owner_plant__plant', filter=Q(pv_site_owner_plant__plant__plant_status='online'), distinct=True ) ) serializer_class = OverviewPlantsActiveSerializer
内容的提问来源于stack exchange,提问作者rsvrt
相关产品推荐
相关产品推荐

