You need to enable JavaScript to run this app. Django中如何同时使用select_related和prefetch_related查询多表数据
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.20 00:54:06