我有以下Django模型:
class Make:
name = models.CharField(max_length=200)
class MakeContent:
make = models.ForeignKey(Make)
published = models.BooleanField()
我想知道是否有可能(不用直接编写SQL),生成一个包含所有Make
和它们相关的MakeContent
,且其中published = True
的查询集。
我有以下Django模型:
class Make:
name = models.CharField(max_length=200)
class MakeContent:
make = models.ForeignKey(Make)
published = models.BooleanField()
我想知道是否有可能(不用直接编写SQL),生成一个包含所有Make
和它们相关的MakeContent
,且其中published = True
的查询集。
是的,我认为您想要
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)
flat = True
的意义在哪里?根据定义,这些 ID 已经是唯一的,再次确保其唯一性可能需要额外的计算。 - pintochmake.make_content_set
应该改为make.makecontent_set
。 - Sam Creamer我知道这是一个很老的问题,但我还是要回答。因为我认为我的答案可以帮到其他人。我对模型进行了一些修改,具体如下。我使用的是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)
为避免重复结果,您应该使用 distinct()
。
Make.objects.filter(makecontent__published=True).distinct()
我希望它能有所帮助。select from make right join makecontent on make.id=makecontent.make_id
,其中在“MakeContent”中有多行具有相同的 make_id
。 - ShadiDjango不支持反向外键查找的select_related()
方法,因此在不离开Python的情况下,你所能做的最好的事情就是进行两个数据库查询。第一个查询是获取包含MakeContents
且published = True
的所有Makes
,第二个查询是获取所有MakeContents
,其中published = True
。然后你必须循环遍历并按照需要排列数据。这是一篇关于如何做到这一点的好文章:
http://blog.roseman.org.uk/2010/01/11/django-patterns-part-2-efficient-reverse-lookups/
让我将Spike的文字答案翻译成代码,以供将来的查看者参考。请注意,每个'Make'都可以有零到多个'MakeContent'。
如果问者的意思是查询具有至少一个已发布的'MakeContent'的'Make',那么Jason Christa的第二个片段回答了这个问题。
该片段相当于
makes = Make.objects.select_related().filter(makecontent__published=True).distinct()
但是,如果提问者想要查询所有已发布的'MakeContent'并且与'Make'相匹配,则跟随上述的'makes'。
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)
包含所需的查询。
Make.objects.exclude(MakeContent_set__published=False)
如果其中至少有一个(就像其他答案中所述):
Make.objects.filter(MakeContent_set__published=True)