You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DRF SerializerMethodField中如何使用_set计算平均评分

错误原因

aggregate()是Django QuerySet(查询集)对象的内置方法,只能作用于多条记录的集合上,不能直接在单个模型实例上调用。
你当前代码中get_average_rating方法接收的instance是单个FeedbackModel实例,直接调用instance.aggregate()必然抛出AttributeError,这是报错的核心原因。
你提到的_set是一对多关系下,从「一」侧模型访问关联「多」侧模型集合的反向关联语法:你的FeedbackModel通过外键business_account关联BusinessAccountModel,且没有自定义related_name,因此从商家实例访问关联所有评价的反向属性为feedbackmodel_set,这个属性返回的就是对应商家下所有评价的QuerySet,支持aggregate()聚合操作。

修复方案

根据你要实现的业务场景,二选一即可:

场景1:返回商家维度的平均评分(绝大多数业务的常规需求)

平均评分是商家维度的统计值,不属于单条评价,你之前把字段写在FeedbackSerializer里是放错了位置,应该迁移到BusiAccSerializer中:

from django.db.models import Avg

class BusiAccSerializer(serializers.ModelSerializer):
    average_rating = serializers.SerializerMethodField()

    def get_average_rating(self, instance):
        # 这里的instance是单个商家实例,通过反向_set拿到所有关联评价的查询集再聚合
        rating_avg = instance.feedbackmodel_set.aggregate(avg=Avg('rating'))['avg']
        # 无评价时默认返回0,可根据业务需求调整
        return round(rating_avg, 1) if rating_avg is not None else 0.0

    class Meta:
        model = BusinessAccountModel
        fields = ['business_title', 'business_description', 'status', 'note', 'user', 'average_rating']

你要找的_set就加在商家实例后面,也就是上面代码里的instance.feedbackmodel_set位置。

场景2:单条评价返回时附带所属商家的平均评分

如果确实需要在评价列表里带出每条评价对应商家的平均评分,只需要修改FeedbackSerializer的聚合逻辑,先取到关联商家再走反向关联查询即可:

from django.db.models import Avg

class FeedbackSerializer(serializers.ModelSerializer):
    feedback_by_user_profile_pic = serializers.ImageField(source='feedback_by.profile_pic')
    average_rating = serializers.SerializerMethodField()

    def get_average_rating(self,instance):
        # 先取当前评价关联的商家,再通过反向_set拿到该商家所有评价聚合
        merchant_feedback_qs = instance.business_account.feedbackmodel_set.all()
        rating_avg = merchant_feedback_qs.aggregate(avg=Avg('rating'))['avg']
        return round(rating_avg, 1) if rating_avg is not None else 0.0

    class Meta:
        model = FeedbackModel
        fields = ['feedback_text','rating','date','feedback_by_user_profile_pic','average_rating']

性能优化建议

如果是列表接口返回数据,上述写法会产生N+1查询问题(每返回一条记录就执行一次聚合查询),建议在视图层提前用annotate把平均评分注到查询结果上,大幅减少数据库查询次数:
以商家列表接口为例,视图层查询集写法:

from django.db.models import Avg

queryset = BusinessAccountModel.objects.annotate(
    average_rating=Avg('feedbackmodel__rating')
)

这种写法下序列化器不需要再写SerializerMethodField,直接声明average_rating = serializers.FloatField()即可取到预计算的评分值,性能提升明显。

内容的提问来源于stack exchange,提问作者Amol_G

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 03:51:28