查询集何时使用_result_cache,而不是访问数据库?

时间:2016-11-21 04:39:35

标签: django orm django-queryset

我对查询集使用其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

所以,我的问题是:

  1. 为什么在点击数据库后None_result_cache
  2. 是否评估查询集意味着None不是_result_cache
  3. 查询集何时使用其var canvas = new fabric.Canvas('canvas'); fabric.loadSVGFromURL('image.svg', function(objects, options) { var obj = fabric.util.groupSVGElements(objects, options); canvas.add(obj).renderAll(); } ,而不是访问数据库?

2 个答案:

答案 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)

希望这能澄清您的所有问题。感谢。