Как получить данные с обеих сторон объединения "многие ко многим" в 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]