多标签过滤时Question点赞数统计异常问题求助
问题描述
当使用1个或2个标签过滤Question时,点赞数显示正确;但使用3个标签过滤时,点赞数会被该Question关联的标签数量相乘,数据库中的点赞数据本身并未发生变化。
相关代码
视图函数代码
def tagAndFilter(request): tags_string = request.GET.get('tags', None) if tags_string: tags_list = [tag.strip() for tag in tags_string.split(',') if tag.strip()] tags = QuestionTag.objects.filter(name__in=tags_list) questions = Question.objects.filter(tags__in=tags).distinct() questions = questions.annotate(likescount=Count('likes')) context = { 'questions': questions } return render(request, 'question/category.html', context)
models.py代码
class Like(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='likes') created_at = models.DateTimeField(auto_now_add=True)
问题分析与解决方案
你指出的questions = questions.annotate(likescount=Count('likes'))确实是问题所在。
原因
当通过多个标签过滤Question时,Django ORM会生成多表关联查询:一个关联了N个目标标签的Question,会在关联后的查询结果集中出现N次。虽然你调用了distinct()对Question去重,但annotate的计数逻辑是基于关联后的重复行执行的,这就导致点赞数被乘以该Question关联的标签数量。
解决方案
有两种可行的修复方式:
方式1:给Count添加distinct参数
直接在Count中指定distinct=True,确保只对唯一的点赞记录计数:
questions = questions.annotate(likescount=Count('likes', distinct=True))
这种方式简洁高效,优先推荐。
方式2:使用子查询统计点赞数
通过子查询单独统计每个Question的点赞数,避免多表关联带来的重复计数问题:
from django.db.models import Subquery, OuterRef # 子查询:统计单个Question的点赞数 likes_subquery = Like.objects.filter(question=OuterRef('pk')).values('question').annotate(count=Count('id')).values('count') questions = questions.annotate(likescount=Subquery(likes_subquery))
内容的提问来源于stack exchange,提问作者Andrey
相关产品推荐
相关产品推荐

