如何在Django中获取查询集中所有对象的所有外键的查询集?

10

我有一个模型(实际上是2个模型,但另一个不那么相关)

class Foo(models.Model):
    ...
    bar = models.ForeignKey(Bar,
        ...
    )

当我有一个Foo的QuerySet时,如何获取该QuerySet引用的所有Bar实例?

由于我正在使用MySQL,无法使用.distinct(['bar'])

3个回答

30
foo_queryset = Foo.objects.filter(attr=value)
referenced_bars = Bar.objects.filter(id__in=foo_queryset.values('bar_id'))

3
这是一个关于文档中 in 字段查询的链接。 - Timmy O'Mahony
我很好奇,这个程序的效率如何?有没有更高效的方法可以实现它? - Algorithmatic
@Algorithmatic - 这是一个非常广泛的问题,它取决于您正在使用的数据库、数据和该数据上的索引。在 MySQL 上运行此查询可能会非常缓慢,因为 MySQL 在处理 Django 生成的子查询方面非常糟糕。为了解决这个问题,您可以执行一个查询来获取 bar_ids,然后将其传递给 __in 子句 Bar.objects.filter(id__in=set(foo_queryset.values('bar_id'))). 显然,如果您有很多 Foo 对象,这也可能很慢。 - Iain Shelvington
在我看来,这可能不是一个高效的解决方案。如果你有成千上万个 bar_id,那该怎么办? - decadenza

0
bars = Bar.objects.filter(foo_set__attr=value)

我的包含相关“Foo”的“QuerySet”应该放在哪里? - Kimvais
我认为 - 可能是错误的想法 - 忽略查询集(少了一个要关心的对象)会是最容易的。相反,直接将此初始查询集的限制/过滤器应用于 Bars。基本上,foo_set__attr=value 只是一个占位符,您可以扩展它以定义您想使用的 Foo。这有帮助吗?还是您坚持使用单独的 Foo 查询集? - schacki

0
你可以使用 foo_queryset.bar_set.all() 来获取你的 Bar 的所有实例。
foo_queryset = Foo.objects.filter(attr=value)
referenced_bars = foo_queryset.bar_set.all()

Django文档中有更多详细信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接