Django Queryset с фильтрацией по обратному внешнему ключу
У меня есть следующая модель Django:
class Make:
name = models.CharField(max_length=200)
class MakeContent:
make = models.ForeignKey(Make)
published = models.BooleanField()
Я хотел бы знать, возможно ли (без прямого написания SQL) для меня генерировать запрос, содержащий все Make
, и каждый из них связан с MakeContent
, где published = True
.
Ответы
Ответ 1
Django не поддерживает метод select_related() для обратного поиска внешнего ключа, поэтому лучше всего обойтись без выхода из Python - это два запроса к базе данных. Первое - захватить все Makes, которые содержат MakeContents, где опубликовано = True, а второе - захватить все опубликованные MakeContents = True. Затем вам нужно пройти и упорядочить данные, как вы этого хотите. Вот хорошая статья о том, как это сделать:
http://blog.roseman.org.uk/2010/01/11/django-patterns-part-2-efficient-reverse-lookups/
Ответ 2
Да, я думаю, вы хотите
make = Make.objects.get(pk=1)
make.make_content_set.filter(published=True)
или, возможно,
make_ids = MakeContent.objects.filter(published=True).values_list('make_id', flat=True)
makes = Make.objects.filter(id__in=make_ids)
Ответ 3
Позвольте мне перевести спайк в ответ на коды для будущих зрителей. Обратите внимание, что каждый "Make" может иметь от нуля до нескольких "MakeContent"
Если искатель означает запрос "Сделать" с помощью AT LEAST ONE "MakeContent" , опубликованный = True, то второй фрагмент ответа Джейсона Кристы отвечает на вопрос.
Отрывок эквивалентен
makes = Make.objects.select_related().filter(makecontent__published=True).distinct()
Но если искатель означает запрос "Сделать" с помощью ВСЕ "MakeContent" , публикация которого опубликована = "Истина", а затем следуя "make" выше,
import operator
make_ids = [m.id for m in makes if
reduce(operator.and_, [c.published for c in m.makecontent_set.all()] )
]
makes_query = Make.objects.filter(id__in=make_ids)
содержит требуемый запрос.
Ответ 4
Я знаю, что это очень старый вопрос, но я отвечаю. Как я думаю, мой ответ может помочь другим. Я немного изменил модель следующим образом. Я использовал Django 1.8.
class Make(models.Model):
name = models.CharField(max_length=200)
class MakeContent(models.Model):
make = models.ForeignKey(Make, related_name='makecontent')
published = models.BooleanField()
Я использовал следующий запрос.
Make.objects.filter(makecontent__published=True)
Надеюсь, это поможет.