You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django:如何获取外键ID且避免额外数据库查询

问题场景

我定义了如下Django模型:

class Photo(models.Model):
    doc_pic = models.ImageField(upload_to='specialist/', default='', null=True, blank=True, max_length=250)
    doctor = models.ForeignKey(Doctor, blank=True, null=True, on_delete=models.SET_NULL, related_name='photos')

执行查询获取照片数据:

temp = Photo.objects.all()

现在想获取第一条数据中doctor字段对应的医生ID,直接执行print(temp[0].doctor)得到的是Doctor对象,而用temp[0].doctor.id虽然能拿到ID,但会触发额外的数据库查询,希望避免这种情况。

解决方案

这个问题本质是Django外键默认的**懒加载(Lazy Loading)**导致的N+1查询问题,这里有两个针对性的解决办法:

1. 直接访问外键的_id后缀属性

Django会自动为每个外键字段生成一个[字段名]_id的属性,这个属性存储的就是关联对象的原始ID值,而且是在初始查询Photo.objects.all()时就已经从数据库获取到的,完全不会触发额外查询。

对你的场景来说,直接用下面的代码就能拿到医生ID:

print(temp[0].doctor_id)

这个方法最直接,如果你只需要ID的话,这是最优解。

2. 用select_related预加载关联对象

如果你之后不仅需要医生ID,还可能用到Doctor对象的其他属性(比如姓名、科室等),那可以在查询时用select_related把关联的Doctor数据一起预加载进来,这样一次查询就把Photo和对应的Doctor数据都拉取完成,后续访问任何Doctor的属性都不会再触发额外查询。

修改后的查询代码:

temp = Photo.objects.select_related('doctor').all()

之后再访问temp[0].doctor.id或者temp[0].doctor.name之类的属性,都不会再去数据库查新数据了。

内容的提问来源于stack exchange,提问作者caliph

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:34:20