Как получить данные с обеих сторон объединения "многие ко многим" в django

Допустим, у меня есть следующие модели:

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"
    )

In plain english, есть набор скважин и в каждой скважине может быть несколько и много различных типов антибиотиков.

Я пытаюсь получить данные о данной скважине и всех содержащихся в ней антибиотиках.

Я пробовал WellConditionAntibiotic.objects.filter(wells__id=1).select_related('antibiotic')

что дает мне такой запрос:

SELECT
    "kingdom_wellconditionantibiotic"."id",
    "kingdom_wellconditionantibiotic"."created_at",
    "kingdom_wellconditionantibiotic"."updated_at",
    "kingdom_wellconditionantibiotic"."volume",
    "kingdom_wellconditionantibiotic"."stock_concentration",
    "kingdom_wellconditionantibiotic"."dosage",
    "kingdom_wellconditionantibiotic"."antibiotic_id",
    "kingdom_antibiotic"."id",
    "kingdom_antibiotic"."created_at",
    "kingdom_antibiotic"."updated_at",
    "kingdom_antibiotic"."name"
FROM
    "kingdom_wellconditionantibiotic"
    INNER JOIN "kingdom_wellconditionantibiotic_wells" ON (
        "kingdom_wellconditionantibiotic"."id" = "kingdom_wellconditionantibiotic_wells"."wellconditionantibiotic_id"
    )
    INNER JOIN "kingdom_antibiotic" ON (
        "kingdom_wellconditionantibiotic"."antibiotic_id" = "kingdom_antibiotic"."id"
    )
WHERE
    "kingdom_wellconditionantibiotic_wells"."well_id" = 1

Это дает мне все данные по антибиотикам, но ни одного из данных по скважинам. Поэтому я попробовал Well.objects.filter(pk=1).select_related(['well_condition_antibiotics', 'antibiotic']).query что привело к ошибке.

Как я могу создать запрос на django, чтобы включить все данные по скважинам и все данные по антибиотикам в скважинах?

Начиная со второй попытки, используя Well, вы должны предварительно выбрать WellConditionAntibiotic, а также выбрать соответствующий антибиотик следующим образом:

from django.db.models import Prefetch


well = Well.objects.filter(pk=1).prefetch_related(
    Prefetch(
        "well_condition_antibiotics",
        queryset=WellConditionAntibiotic.objects.select_related("antibiotic"),
    )
)

Тогда вы можете просто перебирать связанные записи WellConditionAntibiotic с соответствующим антибиотиком:

for well_condition_antiobiotic in well.well_condition_antibiotics.all():
    print(well_condition_antiobiotic.antibiotic.name)

Вы можете найти больше информации о prefetch_related и Prefetch здесь...[Django-doc]

Вернуться на верх