django 缓存教程
Memcached是Django本身支持的最快,最有效的缓存类型
memcache安装
pip3 install python-memcached
# 下载memcached.1.4.5以上的版本,管理员运行cmd
# 配置开机启动
schtasks /create /sc onstart /tn memcached /tr "'c:\memcached\memcached.exe' -m 512"
# 取消开机启动
schtasks /delete /tn memcached
yum -y update
yum install -y libevent libevent-devel
yum install -y memcached
yum install -y php-pecl-memcache
vim /etc/sysconfig/memcached
CACHESIZE="1GB"
OPTIONS="127.0.0.1"
systemctl restart memcached
systemctl restart httpd
缓存配置
- 方法一:绑定到memcached端口
>>> vim settings.py
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
}
}
- 方法二:绑定到本地Unix套接字文件
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': 'unix:/tmp/memcached.sock',
}
}
缓存配置参数
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
# 缓存的默认超时,默认为300秒,None值是缓存键永不过期,值0代表不缓存
'TIMEOUT': 60,
# 缓存中的键的前缀,避免不同站点的缓存冲突
'KEY_PREFIX': 'xiladaili',
'OPTIONS': {
# 缓存中允许的最大条目数,默认为300
'MAX_ENTRIES': 1000
# 每个对象大小限制为2MB
'server_max_value_length': 1024 * 1024 * 2,
}
}
缓存整个站点
Django缓存的三种方式的优先级,全站>单独视图>局部视图,也就是说三种都写了一最高优先级为准。
缓存整个站点和缓存下游需要配置中间件:
#>>> vim settings.py
MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware', # 必须是第一个
'...',
'django.middleware.common.CommonMiddleware',
'...',
'django.middleware.cache.FetchFromCacheMiddleware', # 必须是最后一个
]
然后必须配置下面选项:
#>>> vim settings.py
# 用于存储的缓存别名。
CACHE_MIDDLEWARE_ALIAS = 'xiladaili'
# 每个页面应缓存的秒数
CACHE_MIDDLEWARE_SECONDS = 300
# 键前缀,当多个站点使用同一个配置的时候,这个可以设置可以避免发生冲突,一般设置为网站域名,以防止发生键冲突。如果你不在乎,请使用空字符串。
CACHE_MIDDLEWARE_KEY_PREFIX = 'www.demo.com'
# 那么只有匿名的请求会被缓存,这是一个禁用缓存非匿名用户页面的最简单的做法,注意确保已经启用了Django用户认证中间件(可选)
CACHE_MIDDLEWARE_ANONYMOUS_ONLY = False
缓存整个视图
页面缓存在后端缓冲器(比如memcached)缓存的是Response对象。
完全公共的页面可以使用页面缓存,带有用户隐私的页面不要使用。
#>>> vim views.py
from django.views.decorators.cache import cache_page
@cache_page(60 * 15) # 将视图缓存15分钟
def my_view(request):
...
**注意:**每个视图缓存都是根据URL识别,如果多个URL指向同一个视图,则每个URL将单独缓存。
例如:urlpatterns = [ path('foo/int:code/', my_view), ];请求
/foo/1/
和/foo/23/
将被单独缓存。
为了避免视图与缓存的耦合,通过在URL配置视图缓存:
#>>> vim urls.py
from django.views.decorators.cache import cache_page
urlpatterns = [
path('foo/<int:code>/', cache_page(60 * 15)(my_view)),
]
通过Cookie等不同头部参数缓存不同页面
#>>> vim views.py
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from django.views.decorators.vary import vary_on_cookie, vary_on_headers
# 根据Cookie判断
class Index(View):
@method_decorator(cache_page(600))
@method_decorator(vary_on_cookie)
def get(self, request):
...
# 根据User-Agent + Cookie判断
class Index(View):
@method_decorator(cache_page(600))
@method_decorator(vary_on_headers('User-Agent', 'Cookie'))
def get(self, request):
...
模板片段缓存
模板片段缓存在缓存后端内显示的内容是html片段,也就是直接缓存的html代码片段。
缓存片段:
#>>>vim demo.html
{% load cache %} # 模板顶部附近
...
{% cache 500 sidebar %} # 必须提供的两个参数:缓存超时秒数(None代表永久)、缓存片段名称(名称不能使用变量)
.. sidebar ..
{% endcache %}
**注意:**缓存片段需要放在block块内,如果在block外面可能会导致不缓存。
对站点的每个用户都单独缓存副本:
{% load cache %}
{% cache 500 sidebar request.user.username %}
.. sidebar for logged in user ..
{% endcache %}
在view中获取缓存片段:
from django.core.cache import cache
from django.core.cache.utils import make_template_fragment_key
# cache key for {% cache 500 sidebar username %}
# 获取到缓存的key;参数:缓存片段名称、所有附加参数的列表
key = make_template_fragment_key('sidebar', [username])
cache.has_key(key) # 判断该键是否存在
低级缓存
使用方法:
基本的接口是和:set(key, value, timeout)
key是一个字符串,value可以是任何可选择的Python对象
timeout是可选的,默认是配置文件的caches设置
建议不要存储None,您将无法区分是否有值。
from django.core.cache import cache
#-------------------------判断是否存在----------------------------
cache.has_key(key)
#-----------------------------设置------------------------------
#对键值对缓存30秒
cache.set('my_key', 'hello, world!', 30)
# 批量设置值,返回无法插入的键列表
cache.set_many({'a': 1, 'b': 2, 'c': 3})
# 如果没key则设置并返回True,如果键存在无操作并返回False
cache.add('add_key', 'New value')
# 如果没有得到value,则设置
cache.get_or_set('some-timestamp-key', datetime.datetime.now, 100)
#-----------------------------递增递减----------------------------
# 尝试递增或递减不存在的缓存键,将引发ValueError
# memcached后端,递增和递减操作将是原子的操作
cache.incr('num') # 递增1
cache.incr('num', 10) # 递增10
cache.decr('num') # 递减1
cache.decr('num', 5) # 递减5
# 设置新的到期时间,timeout参数可选,默认为配置文件timeout时间,成功返回True。
# 例:从现在起10秒后过期
cache.touch('key', 10)
#-----------------------------获取------------------------------
cache.get('my_key')
cache.get('my_key', 'default value') # 如果没有值返回自定义默认值
# 批量获取并返回键值对字典(存在缓存中并且没有过期的会被返回)
cache.get_many(['a', 'b', 'c'])
#-----------------------------删除------------------------------
cache.delete('key')
# 批量删除
cache.delete_many(['a', 'b', 'c'])
# 清空缓存
cache.clear()
缓存下游
使用Vary标头
“可变”标头定义了中间缓存代理服务器(squid)缓存机制在构建其缓存密钥时应考虑哪些请求报头
# 这意味着user-agent和cookie的每个组合都将获得自己的缓存值
from django.views.decorators.vary import vary_on_headers
@vary_on_headers('User-Agent', 'Cookie') # 内容不区分大小写
def my_view(request):
...
使用辅助函数的方法:
from django.shortcuts import render
from django.utils.cache import patch_vary_headers
def my_view(request):
...
response = render(request, 'template_name', context)
patch_vary_headers(response, ['Cookie']) # 和上面效果一样
return response
用户通常面临两种缓存:它们自己的浏览器缓存(私有缓存)和它们的提供者的缓存(公共缓存)。
公共缓存由多个用户使用,你不希望你的银行帐号存储在一个公共缓存中,Web应用程序需要一种方法来告诉缓存数据是私有的,哪些是公开的。
解决方案是指出一个页面的缓存应该是“私有的”。在Django中,使用cache_control()
。
from django.views.decorators.cache import cache_control
@cache_control(private=True) # 这个装饰器负责在后面发送适当的HTTP头
def my_view(request):
...
**注意:**缓存控制设置“私有”和“公共”是互斥的。如果应该设置“私有,装饰器确保“公共”指令被移除(反之亦然)
手动修改缓存控制头的方法:
from django.views.decorators.cache import patch_cache_control
from django.views.decorators.vary import vary_on_cookie
@vary_on_cookie
def list_blog_entries_view(request):
if request.user.is_anonymous:
response = render_only_public_entries()
patch_cache_control(response, public=True)
else:
response = render_private_and_public_entries(request.user)
patch_cache_control(response, private=True)
return response
您也可以通过其他方式控制下游缓存
告诉客户端在一定时间内缓存视图max-age 指令
from django.views.decorators.cache import cache_control
@cache_control(max_age=3600)
def my_view(request):
...
如果你做使用缓存中间件,它已经设置
max-age
与值CACHE_MIDDLEWARE_SECONDS
的设置。在这种情况下,自定义max_age
从cache_control()
装饰将优先考虑,并且头部值将被正确地合并。
完全禁用浏览器缓存
from django.views.decorators.cache import never_cache
@never_cache
def myview(request):
...