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

基于Django3.2+DRF3.12.4,如何获取按评分及评论数排序的顶级产品?

问题

使用Django3.2和Django-rest-framework3.12.4,现有Product和ProductRating两个模型(代码如下),需要获取顶级产品,要求按每个产品的平均评分排序,平均评分越高、评论数越多的产品排在越前面。尝试的代码仅能筛选出有评分的产品,无法实现需求。

模型代码

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.utils.translation import gettext_lazy as _

class Product(models.Model):
    user = models.ForeignKey(User, related_name='userprofile', on_delete=models.CASCADE)
    name = models.CharField(_("name"), max_length=50, null=True, blank=True)
    price = models.IntegerField(_("price"), default=0)
    create_time = models.DateTimeField(_("Create time"), default=timezone.now)

class ProductRating(models.Model):
    user = models.ForeignKey(User, verbose_name=_("user"), on_delete=models.CASCADE, null=True, blank=True)
    product = models.ForeignKey(Product, verbose_name=_("product"), on_delete=models.CASCADE)
    stars = models.IntegerField(_("stars"), default=0)
    is_remove = models.BooleanField(_("is_remove"), default=False)
    create_time = models.DateTimeField(_("Create time"), default=timezone.now)

尝试的代码

def get_all_top_rated_projects(self):
    query = self.filter(productrating__isnull=False)
    print(query[0].productrating.object.all())

解决方案

要实现按平均评分降序、评论数降序排序的需求,需要使用Django的聚合函数Avg和Count,同时过滤掉标记为删除的评分记录(is_remove=False)。

完整实现代码

from django.db.models import Avg, Count, Q

def get_all_top_rated_projects(self):
    # 聚合计算每个产品的平均评分和有效评论数
    queryset = self.annotate(
        avg_rating=Avg(
            'productrating__stars',
            filter=Q(productrating__is_remove=False),
            output_field=models.FloatField()
        ),
        rating_count=Count(
            'productrating',
            filter=Q(productrating__is_remove=False)
        )
    )
    # 按平均评分降序,评论数降序排序;无评分的产品默认排最后
    queryset = queryset.order_by('-avg_rating', '-rating_count')
    
    # 如果只需要保留有评分的产品,添加过滤条件
    # queryset = queryset.filter(rating_count__gt=0)
    
    return queryset

代码说明

  • annotate:为每个Product对象添加两个额外字段:
    • avg_rating:计算该产品所有未删除评分的平均分,用output_field=models.FloatField()确保返回浮点数
    • rating_count:统计该产品未删除的评分数量
  • order_by('-avg_rating', '-rating_count'):先按平均分从高到低排序,平均分相同则按评论数从多到少排序
  • 若只需要展示有评分的产品,取消注释filter(rating_count__gt=0)即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 06:40:47