如何使用prefetch_related获取外键关联对象的name字段?
Django 一对多关联查询优化方案
1. 原有实现的性能问题
原有代码存在N+1查询问题:首次查询获取所有ModelA对象为1次查询,之后每遍历一个ModelA对象,都会单独发起一次数据库请求查询关联的ModelB对象,若存在100个ModelA对象,总查询次数会达到101次,是效率低下的核心原因。
2. 视图层核心优化(使用prefetch_related)
在视图中查询modela_list时,使用prefetch_related预加载关联的links数据,将总查询次数固定为2次:
# 替换原有视图中查询modela_list的代码 modela_list = ModelA.objects.prefetch_related("links").all()
prefetch_related的执行逻辑:
- 第一次批量查询所有ModelA对象
- 第二次批量查询所有上述ModelA对象关联的ModelB对象,在Python层面完成数据关联匹配,循环遍历关联数据时无需再访问数据库。
3. 模板代码修正
原有模板存在两处可修正的点:内层循环调用对象错误、模板标签语法空格错误,修正后代码如下:
{% for a in modela_list %} <p>{{ a.name }}</p> {% for link in a.links.all %} <p>Link name: {{ link.name }}</p> {% endfor %} {% endfor %}
4. 进阶可选优化
如果仅需要用到ModelB的name字段,可以自定义Prefetch查询,仅拉取必要字段,减少数据库返回的数据量,进一步提升性能:
from django.db.models import Prefetch modela_list = ModelA.objects.prefetch_related( Prefetch("links", queryset=ModelB.objects.only("name", "A_id")) ).all()
only方法指定仅查询name和关联外键A_id两个字段,避免加载ModelB其他无用字段。
内容的提问来源于stack exchange,提问作者Yeager
相关产品推荐
相关产品推荐

