DJango文档-cache方面一些探究

300 阅读4分钟

之前把博客的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_ALIASCACHE_MIDDLEWARE_SECONDSCACHE_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没有看到有新加的变量。这到底是怎么回事,后面需要研究一下