Django如何高效查询指定分类的Post列表及对应的回复数量
解决方案
一、先调整模型层配置
给ReplyPost的外键字段增加反向关联名,方便后续聚合查询:
# Model.py 修改部分 class ReplyPost(AbstractBaseModel): creator_id = models.ForeignKey( User, on_delete=models.CASCADE, related_name="reply") # 新增related_name参数 post_id = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="replies") body = models.CharField(max_length=250)
二、完整优化后的视图代码
from django.db.models import Count, F @api_view(['GET']) def get_most_recent_posts_by_category(request, category, count): # 单次查询完成过滤、聚合、字段重命名、排序、截取逻辑 post_list = Post.objects.filter( goal_id__category=category ).annotate( # 聚合计算每条Post的回复数 reply_count=Count('replies', distinct=True), # 直接在ORM层完成字段重命名,无需后续处理 goal_description=F('goal_id__description'), post_body=F('body') ).order_by( # 按创建时间倒序,最新的在前 '-created' ).values( # 仅返回需要的字段 'post_body', 'goal_description', 'created', 'reply_count' )[:count] # 取指定条数 # 返回列表需要加safe=False参数 return JsonResponse(list(post_list), status=status.HTTP_200_OK, safe=False)
三、优化说明
- 原代码存在语法错误:你将查询结果转为列表后,直接对列表做字典的键赋值/删除操作,完全无法运行,优化后直接在ORM层处理字段映射,无需额外操作
- 解决回复数统计问题:使用Django ORM的
annotate+Count做聚合,单条SQL完成所有Post的回复数统计,没有N+1查询问题,性能最优 - 减少数据库交互:无需先单独查询匹配分类的Goal列表,直接通过跨外键过滤Post,两次查询合并为一次
- 逻辑补齐:原代码完全没有用到传入的
count参数,也没有按最新时间排序,优化后都做了对应处理 - 返回格式合规:补充
safe=False参数适配列表类型的返回值
内容的提问来源于stack exchange,提问作者user12314098
相关产品推荐
相关产品推荐

