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

如何将Django中average_rating的null值替换为0?

问题描述

我有一个average_rating字段,通过rates字段取值计算平均值,但当rates字段为空时,该字段显示null。

我的views.py代码如下:

class BooksView(viewsets.ModelViewSet):
    serializer_class = BooksSerializer
    queryset = BooksModel.objects.all()
    filter_backends = [filters.DjangoFilterBackend, filtersrest.SearchFilter, filtersrest.OrderingFilter,]
    filterset_class = Myfilter
    filterset_fields = ('genres','date',)
    search_fields = ['title']
    def get_queryset(self):
        return BooksModel.objects.all().annotate(average_rating=models.ExpressionWrapper(Round(Avg('rates__rate'), 2), output_field=models.FloatField()), _sum_users_cart=Count('users__user'))

当前输出示例:

"id": 18,
        "authors": [
            {
                "author": "Андрей курпатов"
            }
        ],
        "age": [],
        "tags": [],
        "users": [],
        "genres": [],
        "rates": [],
        "average_rating": null,
        "sum_users_cart": 0,
        "title": "Мозг и бизнес",
        "desc": "123",
        "url_photo": "https://s1.livelib.ru/boocover/1007572198/o/fde7/Andrej_Kurpatov__Mozg_i_biznes.jpeg",
        "is_published": true,
        "date": "Декабрь 29, 2022",
        "time": "20:20:02"

期望输出将average_rating改为0:

"id": 18,
        "authors": [
            {
                "author": "Андрей курпатов"
            }
        ],
        "age": [],
        "tags": [],
        "users": [],
        "genres": [],
        "rates": [],
        "average_rating": 0,
        "sum_users_cart": 0,
        "title": "Мозг и бизнес",
        "desc": "123",
        "url_photo": "https://s1.livelib.ru/boocover/1007572198/o/fde7/Andrej_Kurpatov__Mozg_i_biznes.jpeg",
        "is_published": true,
        "date": "Декабрь 29, 2022",
        "time": "20:20:02"
解决方案

方法一:数据库查询阶段处理(推荐)

使用Django的Coalesce函数,该函数返回传入参数中的第一个非空值,可直接将Avg的空结果替换为0。

  1. 先导入Coalesce:
from django.db.models import Coalesce
  1. 修改get_queryset中的annotate逻辑:
def get_queryset(self):
    return BooksModel.objects.all().annotate(
        average_rating=models.ExpressionWrapper(
            Round(Coalesce(Avg('rates__rate'), 0), 2), 
            output_field=models.FloatField()
        ), 
        _sum_users_cart=Count('users__user')
    )

这样数据库会直接返回0而非null,无需后续处理。

方法二:序列化器阶段处理

若不想修改查询逻辑,可在BooksSerializer中对字段值进行替换:

方式1:设置默认值

class BooksSerializer(serializers.ModelSerializer):
    average_rating = serializers.FloatField(default=0)

    class Meta:
        model = BooksModel
        fields = '__all__'  # 或指定包含average_rating的字段列表

方式2:使用SerializerMethodField自定义取值逻辑

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

    def get_average_rating(self, obj):
        return obj.average_rating if obj.average_rating is not None else 0

    class Meta:
        model = BooksModel
        fields = '__all__'

此方法在序列化时将null替换为0,适合无需数据库层面处理的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 12:01:52