django我们可以在预取相关模型上选择一个字段吗?

时间:2012-12-20 13:38:22

标签: django

为简单起见,假设这些为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')

2 个答案:

答案 0 :(得分:55)

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

在Django 1.7之前,这是你能做的最好的,即使第二个查询理论上可以选择所有B个对象以及通过{{1}加入的相关C个对象} z

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

Prefetch

这导致只有两个查询(而不是使用foo = A.objects.prefetch_related( Prefetch('a', queryset=B.objects.select_related('z')) ).get(pk=1) 时的三个)并让数据库处理第二个连接,理论上这应该会带来稍微好一点的性能。

答案 1 :(得分:25)

您只需要一次prefetch_related来电:

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

这将预取两个表。在Django 1.7+中,您可以使用Prefetch对象来提高性能,如koniiiik's answer中所示。