Django中SpoilerVote模型annotate返回值均为1的问题排查
问题原因及解决办法
核心问题:分组粒度太细
你这俩查询看似相似,但values()里的字段组合直接决定了分组逻辑,两者完全不同:
FavoriteBook的查询逻辑:
你按book、book__book_title、book__year分组,这三个字段本质都绑定到同一个book实例(后两个是book的属性),实际分组粒度是单本图书。再加上FavoriteBook的unique_together = ['user', 'book']规则,同一本书可以被多个用户收藏,所以Count("book")能正确统计每本书的总收藏次数。SpoilerVote的查询逻辑:
你按spoiler、user、vote三个字段分组,再结合SpoilerVote的unique_together = ['spoiler', 'user']——这意味着同一个用户对同一个spoiler只能投一次票,所以spoiler+user+vote的组合在数据库里每条记录都是唯一的,每个分组里只会有1条数据,Count("spoiler")自然永远返回1。
针对不同需求的修正方案
需求1:统计每个spoiler的总投票数(不区分UP/DOWN)
去掉user和vote,只按spoiler相关字段分组:
# 统计每个spoiler的总投票数 SpoilerVote.objects.values("spoiler", "spoiler__book__book_title") # 按需添加spoiler的关联字段 .annotate(count=Count("id")) .order_by("-count")
需求2:统计每个spoiler的UP、DOWN分别票数
保留spoiler和vote,去掉user字段:
# 统计每个spoiler的UP/DOWN票数分布 SpoilerVote.objects.values("spoiler", "vote") .annotate(count=Count("id")) .order_by("-count")
小提示
用Count("id")代替Count("spoiler")更稳妥,能避免外键关联可能带来的重复计数风险,属于Django ORM统计的好习惯。
内容的提问来源于stack exchange,提问作者orhanodabasi
相关产品推荐
相关产品推荐

