我对查询集使用其user = User.objects.all() # User is one of my models
print(user) # show data in database (hitting the database)
print(user._result_cache) # output is None
len(user) # output is a nonzero number
print(user._result_cache) # this time, output is not None
的时间感到困惑,或者直接命中数据库。
例如(在python shell中):
_result_cache
所以,我的问题是:
None
为_result_cache
?None
不是_result_cache
?var canvas = new fabric.Canvas('canvas');
fabric.loadSVGFromURL('image.svg', function(objects, options) {
var obj = fabric.util.groupSVGElements(objects, options);
canvas.add(obj).renderAll();
}
,而不是访问数据库?答案 0 :(得分:5)
每当评估完成查询集时,查询集都会在self._result_cache
中缓存其数据。这包括迭代查询集,调用bool()
,len()
或list()
,或者挑选查询集。
print()
函数间接调用查询集上的repr()
。 repr()
将评估查询集以将数据包含在字符串表示中,但不会评估完整查询集。相反,它将get a slice查询集并在表示中使用它。当你想要的只是一个简单的字符串表示时,这可以防止大量查询由于仅评估切片,因此不会缓存结果。
当填充缓存时,每个不创建新查询集对象的方法都将使用缓存而不是创建新查询。在您的特定示例中,如果您切换print()
和len()
语句,您的查询集将只访问数据库一次:
user = User.objects.all()
len(user) # complete queryset is evaluated
print(user._result_cache) # cache is filled
print(user) # slicing an evaluated queryset will not hit the database
print(user._result_cache)
答案 1 :(得分:1)
这种行为有一个解释:
当你使用User.objects.all()时,没有命中数据库。当你没有遍历查询集时,_result_cache总是None.But当你调用len()函数时。迭代将通过查询集,数据库将被命中,结果输出也将为该查询集设置result_cahce。 这是Django的len()函数的源代码:
def __len__(self):
# Since __len__ is called quite frequently (for example, as part of
# list(qs), we make some effort here to be as efficient as possible
# whilst not messing up any existing iterators against the QuerySet.
if self._result_cache is None:
if self._iter:
self._result_cache = list(self._iter)
else:
self._result_cache = list(self.iterator())
elif self._iter:
self._result_cache.extend(self._iter)
return len(self._result_cache)
希望这能澄清您的所有问题。感谢。