如何将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。
- 先导入
Coalesce:
from django.db.models import Coalesce
- 修改
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
相关产品推荐
相关产品推荐

