如何通过关系模型选择所有对象

时间:2009-09-09 00:15:11

标签: python django django-queryset

鉴于模型:

class Profile(models.Model):
    user = models.ForeignKey(User, unique=True)

class Thingie(models.Model):
    children = models.ManyToManyField('self', blank=True, symmetrical=False) 

class Relation(models.Model):
    profile = models.ForeignKey(Profile)
    thingie = models.ForeignKey(Thingie)

如何返回包含与给定Thingie相关的所有Profile实例的QuerySet?也就是说,每个具有外键的Profile都可以从Relation和给定的thingie指向它。

我知道所有关于select_related(),以及如何通过迭代来使用它来做到这一点,但我发现迭代刺激性(badoop bah!)。此外,还查看了values_list(),但它并没有做正确的事情。

请帮忙!谢谢!

3 个答案:

答案 0 :(得分:2)

你肯定需要它作为一个查询集吗?如果你只需要它是一个可迭代的,一个简单的表达式就是:

profiles = [r.profile for r in thingie.relation_set.all()]

我不确定列表理解是否算作刺激性迭代,但对我来说这是一种非常直观的pythonic方法。当然,如果你需要它作为一个查询集,你将会用两个查询做一些更复杂的事情,例如:

relation_values = thingie.relation_set.all().values_list('pk', flat=True)
profiles = Profile.objects.filter(relation__in=relation_values)

有关详情,请参阅“in”文档。如果您不需要查询集,我更喜欢第一种方法。哦,如果你只想要不同的配置文件,你可以在第一种方法中使用set(profiles)或在第二种方法中使用distinct() queryset方法。

答案 1 :(得分:0)

您是否在Making queries上阅读了Django文档?它有一个简单的例子来实现你想要的,更具体地说是Lookups that span relationships。请确保将后一个链接中的代码段引用到页面开头的模型代码。

答案 2 :(得分:0)

如果没有定义Profile和Thingie之间的直接关系,你就不能。

最好的方法是将ManyToMany添加到Thingie,指向Profile并使用ManyToMany上的through参数(django docs)来指定您的Relation模型/表。

通过这种方式,您可以对Thingie执行直接过滤操作以获取您的配置文件并仍然存储您的中间关系数据。