Django自引用多对多关系下查询关注用户发布投票的更优实现方案
推荐问题标题:Django如何高效查询已关注用户发布的所有投票内容
现有代码问题
你当前的写法存在非常明显的N+1查询性能问题:第一次查询取关注用户ID,之后每遍历一个用户ID就会分别查询用户表、投票表,关注用户数量越多,数据库查询次数会线性增长,高并发场景下性能会非常差。
最优实现方案
直接用Django ORM的跨关系关联查询,仅需1次数据库查询就能拿到所有符合要求的投票,代码简化到1行:
def all_polls_utils(request): return PollQuestion.objects.filter(user__related_to=request.user)
写法说明
你在CustomUser中定义的自关联多对多字段设置了反向关联名related_name='related_to',即如果用户A关注了用户B,那么B的related_to查询集就会包含A,直接过滤投票发布者的related_to等于当前登录用户,就刚好匹配当前用户关注的所有人发布的投票。
如果偏好更直观的写法,也可以用IN查询,性能比循环拼接好,仅需2次数据库查询:
def all_polls_utils(request): # 加flat=True直接返回ID列表,无需额外拆元组 following_ids = request.user.get_all_followings().values_list("id", flat=True) return PollQuestion.objects.filter(user_id__in=following_ids)
额外优化建议
- 如果需要同时返回投票发布者的信息,在查询集后加
select_related('user')即可避免二次关联查询:PollQuestion.objects.filter(user__related_to=request.user).select_related('user') - 返回的是原生查询集,支持后续直接做排序、分页等操作,惰性查询特性不会带来额外性能损耗
- 你定义的
CustomUser中不需要单独加password字段,AbstractUser已经自带了密码字段,你自定义的字段长度仅15位,完全存不下Django加密后的密码字符串,建议删除自定义的password字段避免后续报错。
内容的提问来源于stack exchange,提问作者Atharva
相关产品推荐
相关产品推荐

