Django Queryset过滤反向外键

时间:2011-03-25 19:40:58

标签: django model filter django-queryset

我有以下Django模型:

class Make:
   name = models.CharField(max_length=200)

class MakeContent:
   make = models.ForeignKey(Make)
   published = models.BooleanField()

我想知道是否可以(不直接编写SQL)生成一个查询集,其中包含所有Make和每个MakeContent的{​​{1}}个published = True

5 个答案:

答案 0 :(得分:54)

是的,我想你想要

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)

答案 1 :(得分:14)

让我将Spike的措辞答案翻译成未来观众的代码。请注意,每个'制作'可以有零到多个' MakeContent'

如果提问者意味着询问“制作”。 至少一个' MakeContent'发表的= True,然后是杰森克里斯塔的第二个片段回答了这个问题。

该代码段相当于

makes = Make.objects.select_related().filter(makecontent__published=True).distinct()

但是,如果提问者意味着询问“制作”。与 ALL ' MakeContent'发表的= True,然后跟随'制作'以上,

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)

包含所需的查询。

答案 2 :(得分:14)

我知道这是一个非常古老的问题,但我正在回答。我认为我的答案可以帮助别人。我已经改变了模型如下。我用过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)

希望它会有所帮助。

答案 3 :(得分:10)

Django不支持反向外键查找的select_related()方法,因此在不离开Python的情况下,您可以做的最好的事情是两个数据库查询。第一种方法是抓取Makes包含MakeContents published = True的所有MakeContents,第二种方法是抓取所有published = True {{1}}。然后,您必须循环并按您希望的方式排列数据。这是一篇关于如何做到这一点的好文章:

http://blog.roseman.org.uk/2010/01/11/django-patterns-part-2-efficient-reverse-lookups/

答案 4 :(得分:1)

再过一次,不清楚是什么问题,但是如果需要所有相关的MakeContent对象都已经发布,则可以这样做:

String

如果其中至少有一个(与其他答案一样):

Make.objects.exclude(MakeContent_set__published=False)