Django外键关联模型查询:统计帖子点赞数并传递至前端
解决Django中批量统计帖子点赞数的问题
核心解决方案
用Django ORM的annotate()结合Count()方法,一次SQL查询就能批量统计所有帖子的点赞数,彻底避免循环单帖查询的N+1性能问题。
针对你的模型的具体实现
1. 优化模型(可选但推荐)
你的LikeMatrix模型中,post字段的related_name设为post不够直观,建议修改为likes,方便后续理解和维护:
class LikeMatrix(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="liker") # 修改related_name为likes post = models.ForeignKey(Posts, on_delete=models.CASCADE, related_name="likes") def __str__(self): return f"{self.user} likes {self.post} post"
2. 视图层批量统计点赞数
在views.py中,替换原来的帖子查询代码,用annotate()给每个Posts对象添加点赞数字段:
from django.db.models import Count def your_view(request): # 批量统计每个帖子的点赞数,同时提前加载关联的用户信息避免额外查询 allPosts = Posts.objects.select_related('user')\ .annotate(likes_count=Count('likes'))\ .order_by('-id') # 等同于原来的reverse(),写法更规范 # 其他业务逻辑... return render(request, 'index.html', {'pagePosts': allPosts})
如果不修改related_name,则把Count('likes')改成Count('post')即可,因为当前post字段的related_name是post。
3. 模板中显示点赞数
把模板中所有{{post.likes}}替换为{{post.likes_count}},示例修改如下:
<!-- 原代码 --> <label id="postLikes">{{post.likes}}</label> <!-- 修改后 --> <label id="postLikes">{{post.likes_count}}</label> <!-- 其他类似位置同步修改 --> <label id="likesNum">{{post.likes_count}}</label>
性能对比说明
- 你之前用
len(LikeMatrix.objects.filter(post=post_id))的方式,每处理一个帖子就会发起一次SQL查询,当帖子数量多的时候会产生大量重复查询,性能极低。 - 用
annotate()+Count()的方式,Django会生成一次包含分组统计的SQL查询,一次性获取所有帖子及其点赞数,性能提升显著。
内容的提问来源于stack exchange,提问作者Gidgey
相关产品推荐
相关产品推荐

