Подтвердить что ты не робот

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.

4b9b3361

Ответ 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)

Надеюсь, это поможет.