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

如何在Django中获取多对多关联双方的数据?

问题:获取指定Well及其关联的所有抗生素数据

模型定义

class Well(TimeStampMixin, models.Model):
    plate = models.ForeignKey(Plate, on_delete=models.CASCADE, related_name="wells")
    row = models.TextField(null=False)
    column = models.TextField(null=False)

    class Meta:
        unique_together = [["plate", "row", "column"]]


class Antibiotic(TimeStampMixin, models.Model):
    name = models.TextField(null=True, default=None)


class WellConditionAntibiotic(TimeStampMixin, models.Model):
    wells = models.ManyToManyField(Well, related_name="well_condition_antibiotics")
    volume = models.IntegerField(null=True, default=None)
    stock_concentration = models.IntegerField(null=True, default=None)
    dosage = models.FloatField(null=True, default=None)
    antibiotic = models.ForeignKey(
        Antibiotic, on_delete=models.RESTRICT, related_name="antibiotics"
    )

需求是获取指定Well的所有数据,以及其关联的全部Antibiotic数据。

已尝试的方法:

  1. 使用WellConditionAntibiotic.objects.filter(wells__id=1).select_related('antibiotic'),能获取抗生素数据,但无法获取Well本身的数据。
  2. 使用Well.objects.filter(pk=1).select_related(['well_condition_antibiotics', 'antibiotic']).query,出现错误。

解决方案

要同时获取Well数据和关联的抗生素数据,需要结合prefetch_related和select_related,核心逻辑如下:

  • select_related 仅适用于外键/一对一关系,通过SQL JOIN一次性获取关联对象。
  • prefetch_related 适用于多对多/反向外键关系,先查询主对象,再批量查询关联对象,避免N+1查询问题。

针对你的模型,well_condition_antibiotics是Well的多对多反向关联,需要用prefetch_related;而每个WellConditionAntibiotic关联一个Antibiotic(外键),可以用select_related提前获取。

正确查询语句

from django.db.models import Prefetch

# 获取指定ID的Well,同时预取关联的WellConditionAntibiotic及对应的Antibiotic
well = Well.objects.filter(pk=1).prefetch_related(
    Prefetch(
        'well_condition_antibiotics',
        queryset=WellConditionAntibiotic.objects.select_related('antibiotic')
    )
).first()

数据访问方式

  • 访问Well自身数据:直接使用well.row、well.column等属性。
  • 访问关联的抗生素相关数据:
# 遍历所有关联的WellConditionAntibiotic对象
for wca in well.well_condition_antibiotics.all():
    print(f"抗生素名称: {wca.antibiotic.name}")
    print(f"剂量: {wca.dosage}")
    print(f"体积: {wca.volume}")

该查询只会执行2次SQL:一次查询Well数据,一次批量查询关联的WellConditionAntibiotic和Antibiotic数据,避免了额外的数据库请求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 05:30:52