之前把博客的cache换成了redis,在配置时候,好奇了一下django什么时候才用到cache。之前在公司写业务代码都没有研究过,今天看了一下文档,收获了一点。实践的同时,也记下一些感觉有需要的笔记。
The per-site cache
前面既然把cache配了起来,那么我们就可以用网站来缓存我们的网站页面,使得我们不需要每次请求页面都重新计算生成整个页面。我们需要把**'django.middleware.cache.UpdateCacheMiddleware'和'django.middleware.cache.FetchFromCacheMiddleware'到我们的 MIDDLEWARE
**配置中。如下:
MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
]
这几个中间件的顺序有将就的:首先UpdateCacheMiddleware必须在最上面,FetchFromCacheMiddleware必须要最后。这样主要的目的是:返回response时候最后一个走UpdateCacheMiddleware,这样来更新cache里面的数据。而FetchFromCacheMiddleware要在request时候第一个走,这样当缓存里面有对应的页面时候,就可以直接返回缓存的数据了。
如果网站采用这种缓存方式的话,setting文件有3个配置项可以配置的(这里不配保持默认):
CACHE_MIDDLEWARE_ALIAS
,CACHE_MIDDLEWARE_SECONDS
,CACHE_MIDDLEWARE_KEY_PREFIX
per-site cache的配置,会把整个站点都缓存掉。什么意思呢?django文档的意思是,只要你GET和HEAD请求返回页面是200状态码,同时请求头允许接受缓存的话,唯一的(url+请求参数)将会被认为是一个唯一的请求页面。这个站点下的所有页面(包括admin等等),都会被缓存。一般来说我们也不会用这个配置。
The per-view cache
django.views.decorators.cache.cache_page()
一个常规的django使用缓存的方式,不是前面所说的缓存整个站点,而是缓存各个需要缓存的view。django.views.decorators.cache定义了一个cache_page装饰器,这个装饰器可以自动缓存对应view的response。用法如下:
from django.views.decorators.cache import cache_page
@cache_page(60 * 15)
def my_view(request):
...
和之前的整站缓存一样,这个cache_page缓存判定也是根据唯一的(url+请求参数),具体参数这里就不多说了。基本来说可以配置前缀,缓存时长,指定缓存库等信息。
Specifying per-view cache in the URLconf
如果说前面的对view进行缓存感觉会不方便或者过分侵入代码啥的,文档还提及了一种方法:
from django.views.decorators.cache import cache_page
urlpatterns = [
path('foo/<int:code>/', cache_page(60 * 15)(my_view)),
]
这样的话,我们直接可以在url配置时候就缓存对应的view了。
Template fragment caching
这种使用缓存的方式,就是在模板页面的对应block中使用缓存了,具体参数不啰嗦了:
{% load cache %}
{% cache 500 sidebar %}
.. sidebar ..
{% endcache %}
当然了,如果稍微动态一点的也行,你可以加多个参数使得缓存的更加独立一点,比如以用户姓名为参数的:
{% load cache %}
{% cache 500 sidebar request.user.username %}
.. sidebar for logged in user ..
{% endcache %}
等等等等,这部分看文档就行了,都是语法的用法。
The low-level cache API
如果你想更加客制化的使用django的cache的话,那么django提供了The low-level cache API:
>>> from django.core.cache import caches
>>> cache1 = caches['myalias']
>>> cache2 = caches['myalias']
>>> cache1 is cache2
True
值得注意的是,这里是线程安全的。
To provide thread-safety, a different instance of the cache backend will be returned for each thread.
当然了,如果你在setting没有设多个cache的话,直接下面这样用就可以返回默认的了
from django.core.cache import cache
接下来是基础使用语法,就不阐述了,直接附上代码看了就知道怎么用了:
>>> cache.set('my_key', 'hello, world!', 30)
>>> cache.get('my_key')
'hello, world!'
>>> # Wait 30 seconds for 'my_key' to expire...
>>> cache.get('my_key')
None
>>> cache.get('my_key', 'has expired')
'has expired'
>>> cache.set('add_key', 'Initial value')
>>> cache.add('add_key', 'New value')
>>> cache.get('add_key')
'Initial value'
>>> cache.get('my_new_key') # returns None
>>> cache.get_or_set('my_new_key', 'my new value', 100)
'my new value'
>>> import datetime
>>> cache.get_or_set('some-timestamp-key', datetime.datetime.now)
datetime.datetime(2014, 12, 11, 0, 15, 49, 457920)
>>> cache.set('a', 1)
>>> cache.set('b', 2)
>>> cache.set('c', 3)
>>> cache.get_many(['a', 'b', 'c'])
{'a': 1, 'b': 2, 'c': 3}
......
基本阅读笔记就是这个,唯一奇妙的是,我之前是配了wagtail文档说的Django’s cached template loader,但是发现在redis没有看到有新加的变量。这到底是怎么回事,后面需要研究一下