Django如何用单个QuerySet获取作者及关联文章数据并渲染模板
Django 单QuerySet实现作者+关联文章查询方案
结论
完全可以仅用单个QuerySet实现需求,相比原两次查询的写法性能更优,也更符合Django ORM的设计规范。
实现步骤
1. 视图层修改
只需要查询目标作者实例,通过prefetch_related预加载该作者关联的所有文章,避免后续遍历文章时产生额外的SQL查询,整个过程仅需要1-2次数据库查询,仅返回单个作者对象到模板即可:
def index(request): # 单个QuerySet:查询名字为Peter的作者,同时预加载其所有关联文章 autor = Autor.objects.filter(first_name='Peter').prefetch_related('post_set').first() return render(request, 'posts.html', {'autor': autor})
2. 模板层修改
直接通过作者实例的反向关联属性获取所有文章,不需要再单独传入文章列表:
<!-- 展示作者信息 --> Author: {{ autor.first_name }}, {{ autor.last_name }} <!-- 遍历展示该作者所有文章 --> Posts: {% for post in autor.post_set.all %} <p>{{ post.id }}, {{ post.post }}</p> <p></p> {% endfor %}
原理解释
- 你定义的
Post模型通过ForeignKey关联Autor,Django ORM会自动给Autor模型生成反向关联管理器,默认命名为post_set,可以直接用它查询该作者关联的所有Post数据。 prefetch_related会在查询Autor的同时,提前把该作者对应的所有Post数据查询出来缓存,避免模板遍历文章时每次都发新的数据库请求,解决N+1查询问题。
注意事项
- 如果要自定义反向关联的名称,可以在
Post的ForeignKey字段上添加related_name参数,比如autor = models.ForeignKey(Autor, on_delete=models.CASCADE, related_name='posts'),之后模板就可以用autor.posts.all来遍历文章,可读性更高。 - 要做好空值判断,如果不存在名为Peter的作者,
autor会是None,直接调用属性会报错,可以在模板外层加{% if autor %}包裹内容,或者在视图层提前处理不存在的情况。 - 如果你确定要从
Post侧查询也可以,写法是Post.objects.filter(autor__first_name='Peter').select_related('autor'),但该方案如果作者没有发布任何文章,就无法获取作者信息,适用场景更受限。
内容的提问来源于stack exchange,提问作者gio
相关产品推荐
相关产品推荐

