Фильтрация данных из объединяющей таблицы в Django по внешнему ключу
У меня есть классы моделей, которые выглядят следующим образом:
class Wine(models.Model):
wine_id = models.IntegerField(blank=True, null=False, primary_key=True)
wine_name = models.TextField(blank=True, null=True)
wine_type = models.TextField(blank=True, null=True)
wine_year = models.IntegerField(blank=True, null=True)
wine_alcohol = models.FloatField(blank=True, null=True)
wine_country = models.TextField(blank=True, null=True)
wine_price = models.FloatField(blank=True, null=True)
class Meta:
managed = False
db_table = 'wine'
class Flavor(models.Model):
flavor_id = models.IntegerField(primary_key=False)
flavor_name = models.TextField(blank=True, null=True)
class Meta:
managed = False
db_table = 'flavor'
и одна соединительная таблица между этими двумя:
class FlavorWine(models.Model):
flavor_wine_id = models.IntegerField(blank=True, null=False, primary_key=True)
flavor_group = models.TextField(blank=True, null=True)
flavor_count = models.IntegerField(blank=True, null=True)
wine_id = models.ForeignKey('Wine', on_delete=models.DO_NOTHING)
flavor_id = models.ForeignKey('Flavor', on_delete=models.DO_NOTHING)
class Meta:
managed = False
db_table = 'flavor_wine'
Теперь, когда я пытаюсь получить данные, я получаю ошибки. Я пробовал использовать примеры, приведенные в: Django Filter by Foreign Key и Django: join two tables, но безуспешно.
Я пытался:
wines = Wine.objects.filter(wine_id=wine_id)
wine_flavor = FlavorWine.objects.filter(wine_id__in=wines.values('wine_id'))
return HttpResponse(serializers.serialize('json', wine_flavor, fields=('wine_id', 'flavor_group', 'flavor_count', 'flavor_id')))
и
wine_flavor = serializers.serialize('json', FlavorWine.objects.filter(wine_id_id__gt=wine_id), fields=('wine_id', 'flavor_group', 'flavor_count', 'flavor_id'))
и
wine_flavor = serializers.serialize('json', FlavorWine.objects.filter(wine_id__flavorwine__exact=wine_id), fields=('wine_id', 'flavor_group', 'flavor_count', 'flavor_id'))
И различные комбинации, которые были предложены, но ни одна из них не работает, либо сбой при соединении таблиц, либо не может найти нужное поле. Я всегда получаю подсказку:
HINT: Возможно, вы хотели сослаться на колонку "flavor_wine.wine_id".
То есть, это именно та колонка, на которую я пытаюсь сослаться, но я не могу найти правильный способ сделать это.
Для фильтрации по ForeignKey можно просто передать экземпляр этой модели
В вашем первом методе:
wine_flavor = FlavorWine.objects.filter(wine_id__in=wines.values('wine_id'))
если wine_id является экземпляром Wine model, то вы можете просто написать
wine_flavor = FlavorWine.objects.filter(wine_id=wine_id)
и если wine_id является списком идентификаторов из Wine model, то вы можете просто сделать следующее:
wine_flavor = FlavorWine.objects.filter(wine_id__id__in=wine_id)
Позвольте мне объяснить, что делает приведенная выше строка,
предположим, что wine_id = ['1', '2', '3',....]. где '1' представляет id из Wine model
отфильтруйте их из FlavorWine(FlavorWine.objects.filter)
Где id из Модель вина(wine_id__id) находится в list(wine_id)
(если вам нужна дополнительная помощь, прокомментируйте ниже, я могу обновить свой ответ соответствующим образом)
Итак, чтобы отфильтровать связанные модели по foreignkey, достаточно просто использовать функцию prefetct_ralated, которая принимает аргумент связанного имени модели. Как в моем примере ниже. Вот ссылка, чтобы прочитать больше, чтобы помочь вам понять запрос с prefetch related. https://docs.djangoproject.com/en/4.0/ref/models/querysets/#prefetch-related
wines = Wine.objects.prefetch_related('flavorwine_set').filter(wine_id=wine_id)
wine_flavor = FlavorWine.objects.prefetch_related('flavorwine_set').filter(wine_id__in=wines.values('wine_id'))
Попробуйте воспользоваться этой статьей, https://www.django-antipatterns.com/antipattern/foreign-key-with-id-suffix.html и посмотрите, устранит ли она вашу проблему.
Основная причина, по которой это проблема, заключается в том, что сама .other_model не хранит id. Действительно, Django создает неявное двойное поле с суффиксом _id, которое хранит первичный ключ
.