django可以在已计算的queryset上使用prefetch_related,而无需重新执行初始查询

时间:2021-04-26 04:07:43

consider this code

考虑这段代码

users = UserProfile.objects.all()[:10]
# evaluate the query set
users_list = list(users)

users = users.prefetch_related('posts')

i want to know that using prefetch_related on queryset after it is evaluated will repeat the query on UserProfile model or not. Thanks.

我想知道,在对queryset进行评估后使用prefetch_related是否会重复UserProfile模型上的查询。谢谢。

3 个解决方案

#1


1  

No. Until you evaluate it again, as it cannot magically pull the extra data from the database.

不。直到您再次评估它,因为它不能神奇地从数据库中提取额外的数据。

>>> from django.db import connection
>>> from app.models import Foo
>>> bar = Foo.objects.all()[:1]
>>> len(connection.queries)
0
>>> bar_list = list(bar)
>>> len(connection.queries)
1
>>> bar = bar.prefetch_related('thing')
>>> len(connection.queries)
1
>>> bar_list = list(bar)
>>> len(connection.queries)
2

#2


0  

No, in this scenario, the query will hit only when you call the variable users.

不,在这种情况下,查询仅在调用变量users时才会被命中。

print users

Hit:

冲击:

(0.000) QUERY = 'SELECT “userprofile"."id" INNER JOIN “posts" ON ( “userprofile"."usuari...

#3


0  

As explained here, the QuerySet API executes the database query at the first time you iterate over it. In your case the iteration happens because of the list(users).

如前所述,QuerySet API在第一次迭代数据库查询时执行。在您的例子中,迭代是因为列表(用户)。

The prefetch_related function would have an effect on the first query if you would call it before execution.

prefetch_related函数将对第一个查询产生影响,如果您在执行之前调用它。

So, that means: Yes, you can call prefetch_related after iteration, but the QuerySet has to do a new database query to get the missing information about the posts. QuerySets are cloned every time you call a function like prefetch_related. So, the next iteration is the first one for the cloned object.

因此,这意味着:是的,您可以在迭代之后调用prefetch_related,但是QuerySet必须执行一个新的数据库查询,以获取关于文章的丢失信息。每次调用诸如prefetch_related这样的函数时,就会克隆出queryset。因此,下一个迭代是克隆对象的第一个迭代。

#1


1  

No. Until you evaluate it again, as it cannot magically pull the extra data from the database.

不。直到您再次评估它,因为它不能神奇地从数据库中提取额外的数据。

>>> from django.db import connection
>>> from app.models import Foo
>>> bar = Foo.objects.all()[:1]
>>> len(connection.queries)
0
>>> bar_list = list(bar)
>>> len(connection.queries)
1
>>> bar = bar.prefetch_related('thing')
>>> len(connection.queries)
1
>>> bar_list = list(bar)
>>> len(connection.queries)
2

#2


0  

No, in this scenario, the query will hit only when you call the variable users.

不,在这种情况下,查询仅在调用变量users时才会被命中。

print users

Hit:

冲击:

(0.000) QUERY = 'SELECT “userprofile"."id" INNER JOIN “posts" ON ( “userprofile"."usuari...

#3


0  

As explained here, the QuerySet API executes the database query at the first time you iterate over it. In your case the iteration happens because of the list(users).

如前所述,QuerySet API在第一次迭代数据库查询时执行。在您的例子中,迭代是因为列表(用户)。

The prefetch_related function would have an effect on the first query if you would call it before execution.

prefetch_related函数将对第一个查询产生影响,如果您在执行之前调用它。

So, that means: Yes, you can call prefetch_related after iteration, but the QuerySet has to do a new database query to get the missing information about the posts. QuerySets are cloned every time you call a function like prefetch_related. So, the next iteration is the first one for the cloned object.

因此,这意味着:是的,您可以在迭代之后调用prefetch_related,但是QuerySet必须执行一个新的数据库查询,以获取关于文章的丢失信息。每次调用诸如prefetch_related这样的函数时,就会克隆出queryset。因此,下一个迭代是克隆对象的第一个迭代。