Django中如何同时使用select_related和prefetch_related查询多表数据
实现方案
Django 中针对不同的关联关系有不同的关联查询优化方法:
select_related仅支持 一对一(OneToOneField)、正向外键 关联,本质是通过 SQL JOIN 单次查询同步获取关联表数据prefetch_related用于处理 一对多、多对多 关联,会分两次查询主表、关联表数据后在 Django 层完成结果拼接,避免循环查询的性能损耗
你当前场景中 User 和 UserForm 是一对一关系,User 和 UserAddress 是一对多关系,组合使用两个方法即可实现单次查询链路获取三个模型的数据:
# 外键未设置 related_name 时,默认反向关联字段名为 小写模型名_set objs = User.objects.select_related("userform").prefetch_related("useraddress_set").get(user_id=1)
数据访问示例
获取到查询结果后可直接访问关联数据,不会触发额外的数据库查询:
- 访问 User 自身字段:
objs.name、objs.phone - 访问关联 UserForm 字段:
objs.userform.access_info、objs.userform.etc_comment - 遍历访问关联的所有 UserAddress 数据:
for addr in objs.useraddress_set.all(): print(addr.address_name, addr.address_name_detail)
进阶优化(可选)
如果需要对预取的 UserAddress 做过滤、排序等操作,可以搭配 Prefetch 对象实现:
from django.db.models import Prefetch # 示例:仅预取地址类型为"家"的地址,存到自定义属性 home_addresses 中 objs = User.objects.select_related("userform").prefetch_related( Prefetch( "useraddress_set", queryset=UserAddress.objects.filter(address_type="家").order_by("-created_at"), to_attr="home_addresses" ) ).get(user_id=1) # 直接访问过滤后的地址列表 print(objs.home_addresses)
内容的提问来源于stack exchange,提问作者SeongEon Jo
相关产品推荐
相关产品推荐

