假设我有以下代码:
qs = Users.objects.all()
list = []
for i in range(10):
list.append(qs.filter(age=i))
这里过滤器被调用10次,它连接到数据库10次还是第一次使用过滤器,分配了qs
(由于是惰性的),并且局部应用了过滤器(总计一个数据库连接)?
答案 0 :(得分:1)
这里的过滤器被调用10次,它是否连接到数据库10次,还是第一次使用过滤器。
调用.filter(…)
时,Django不执行查询。您仅构造一个QuerySet
。仅当您消费一个QuerySet
(例如,对它进行迭代,下标或在对象上调用len(…)
)时,您才能查询。
如果您随后在此过程中迭代所有查询集,例如:
for myqs in mylist:
for obj in myqs:
print(obj)
您将进行十个独立的查询,这是针对每个评估的查询集的查询。
如果您遍历查询集,则Django将在数据库上运行查询,并将结果(记录列表)存储在QuerySet
中。因此,这意味着如果您对该查询集进行 second 次迭代,它将不会第二次运行查询,而是 reuse 缓存在QuerySet
中的结果
请注意,下标myqueryset[0]
将进行查询以获取单个对象。如果第二次这样做,它将再次在数据库上运行查询。
已经实现了诸如Haxl [GitHub]之类的某些技术来“分批查询”,并且在需要其中一项结果的情况下,所有查询都将合并到数据库中。但是据我所知,Django目前不支持Haxl。