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。因此,下一个迭代是克隆对象的第一个迭代。