django中的Queryset的两大特性---惰性 and 缓存

①惰性

②缓存

Queryset是可迭代的查询集,而不是简单的列表,查询集中包含了多个查询结果对象。解析来来一下这两大特性。

一、惰性

results = Test.objects.all() # 此时并不会进行实际的数据库查询

list_results = [for result in results] # 只有在实际使用迭代的时候才会进行数据库的查询

二、缓存

根据上面实际查询数据库后返回的list_results列表对象。Django会将结果集缓存在list_results之中。

下次如果仍然查询相关数据时,就会访问list_results,而不会进行数据库的交互。

举个Rest-framework框架中的一个get_queryset的例子:

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def get_queryset(self):
"""
Get the list of items for this view.
This must be an iterable, and may be a queryset.
Defaults to using `self.queryset`.

This method should always be used rather than accessing `self.queryset`
directly, as `self.queryset` gets evaluated only once, and those results
are cached for all subsequent requests.

You may want to override this if you need to provide different
querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)
"""
assert self.queryset is not None, (
"'%s' should either include a `queryset` attribute, "
"or override the `get_queryset()` method."
% self.__class__.__name__
)
# 只需要调用一次self.queryset
queryset = self.queryset
if isinstance(queryset, QuerySet):
# Ensure queryset is re-evaluated on each request.
queryset = queryset.all()
return queryset

说明:源码中的提示

1
2
3
This method should always be used rather than accessing `self.queryset`
directly, as `self.queryset` gets evaluated only once, and those results
are cached for all subsequent requests.

上述这句话告诉我们get查询集的时候尽量调用get_queryset方法,而不是self.queryset属性,这样可以充分利用django提供的Queryset的缓存特性,防止多次交互数据库,增大数据库压力,封装方法只需要访问一次数据库,以后的访问直接从缓存中读取。