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

Far*_*ion 36 django

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

class A():

    a = manytomany('B')

class B():

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

class C():

    c = charfield()
Run Code Online (Sandbox Code Playgroud)

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

foo = A.objects.get(pk = 1).prefetch_related('a').select_related('a__z')
Run Code Online (Sandbox Code Playgroud)

kon*_*iik 58

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

在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)
Run Code Online (Sandbox Code Playgroud)

这导致只有两个查询(而不是使用时的三个prefetch_related('a__z'))并让数据库处理第二个连接,理论上这应该会导致稍微好一点的性能.

  • 这太棒了!我不知道Prefetch.谢谢.对于将来使用它的任何人都要注意:`Prefetch`在模型导入空间中,因此要导入它以使用它,例如:`from django.db.models import Prefetch` (5认同)

Ala*_*air 26

你只需要一个prefetch_related电话:

foo = A.objects.prefetch_related('a__z').get(pk=1)
Run Code Online (Sandbox Code Playgroud)

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