39

为了简单起见,假设这些是 django 模型:

class A():

    a = manytomany('B')

class B():

    b = charfield()
    z = foreignkey('C')

class C():

    c = charfield()

我们可以做这样的事情来获取z也:

foo = A.objects.get(pk = 1).prefetch_related('a').select_related('a__z')
4

2 回答 2

59

这个答案对于 1.7 之前的 Django 版本是正确的。它产生三个查询:首先,获取 的实例A,然后获取其相关的实例,B最后获取与第二个查询中获取的实例C相关的实例。B

在 Django 1.7 之前,这是您能做的最好的事情,尽管理论上第二个查询可以选择所有B对象以及C通过z ForeignKey.

从 Django 1.7 开始,有一个更高级的django.db.models.Prefetch类可以让你做到这一点。您可以自Prefetch定义用于预取相关对象的查询集,如下所示:

foo = A.objects.prefetch_related(
    Prefetch('a', queryset=B.objects.select_related('z'))
).get(pk=1)

这只会产生两个查询(而不是使用 时的三个prefetch_related('a__z')),并让数据库处理第二个连接,理论上这应该会带来更好的性能。

于 2014-10-19T15:08:19.723 回答
30

您只需要一个prefetch_related电话:

foo = A.objects.prefetch_related('a__z').get(pk=1)

这将预取两个表。在 Django 1.7+ 中,您可以通过使用Prefetch对象来提高性能,如koniiiik 的回答

于 2012-12-20T13:57:50.680 回答