一. 站点级缓存模式的设置
需要把'django.middleware.cache.UpdateCacheMiddleware' 和'django.middleware.cache.FetchFromCacheMiddleware' 添加到你的 MIDDLEWARE_CLASSES 设置里, 如例子所示:
MIDDLEWARE_CLASSES = (
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
)
'update'中间件,必须放在列表的开始位置,而fectch中间件,必须放在最后。
二. 不缓存的页面设置
需要在指定的view上设置@never_cache装饰器。
from django.views.decorators.cache import never_cache
@never_cache
@http_response
def never_cache_view(request, *args, **kwargs):
pass
三. 定向删除指定页面的缓存
django的cache api 默认提供了get, set,delete,用于实现对cache的控制。删除指定页面的缓存的话,就需要用到此页面在cache中的key,这个key是如何产生的呢? 看下面源码:
django.utils.cache.py line 188-206
cache_page key 的生成需要四部分:
1.key_prefix 对应settings中的CACHE_MIDDLEWARE_KEY_PREFIX;
2.method 对应GET / HEAD;
3.根据url生成的加密串 ;
4.遍历request.META,以此生成的加密串。
cache_header key 则只需key_prefix和根据url生成的加密串。
例如地址http://127.0.0.1:8000/ji/对应的cache key:views.decorators.cache.cache_header..5d32bb1ec7519c59f5e59a75cd3105a4.Asia/Shanghaiviews.decorators.cache.cache_page..GET.5d32bb1ec7519c59f5e59a75cd3105a4.66816775a6e6a610be240bd1018798ea.Asia/Shanghai
如果我们用cache api 默认的delete方法去删除指定页的缓存的话,我们需要一个完整的key,而以上生成key的第4条我们并不知道。但好在知道指定页的url ,可以依据同样方法生成url的加密串,这样就可以去遍历chache的key,把需要删除的key给找出来,再去执行delete方法。
直接用cache去做遍历是行不通的,the cache is not iterable
但Django LocMemCache 存储的是simple dict, 里面有_cache,可以通过cache._cache.keys()取到cache的所有key,如果key中包含指定url的加密串,就把这个key的cache给delete:
for key in cache._cache.keys():
if '5d32bb1ec7519c59f5e59a75cd3105a4 'in key:
cache.delete(key)
但是 ,这样还是行不通,打印出来发现key是这样的:
cmportal:1:views.decorators.cache.cache_page..GET.5d32bb1ec7519c59f5e59a75cd3105a4.66816775a6e6a610be240bd1018798ea.Asia/Shanghai
还需要处理一下:
for key in cache._cache.keys():
if '5d32bb1ec7519c59f5e59a75cd3105a4' in key:
key = key[key.index('v'):]
cache.delete(key)
测试ok。另外,清除缓存方法所在的view 应该是@never_cache的。
这样,在后台程序对页面配置进行更改后就可以清除指定页面的缓存了。
----------------------- 以上是针对LocMemCache的解决方案--------------------------
如果服务器端用的是redis做缓存,则更容易实现:
1. 配置settings.py
CACHE_REDIS = 'cacheredis'
CACHE_REDIS: {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}CACHE_MIDDLEWARE_ALIAS = CACHE_REDIS
CACHE_MIDDLEWARE_SECONDS = 60*60*24*5
https://niwinz.github.io/django-redis/latest/#_installation
清除缓存的view中:
@never_cache
@http_response
def clear_cache_view(request, *args, **kwargs):
cache_alias = settings.CACHE_MIDDLEWARE_ALIAS
cache = caches[cache_alias]
key_list = cache.iter_keys("*5d32bb1ec7519c59f5e59a75cd3105a4*")
for key in key_list:
if key:
cache.delete(key)
logging.info("key deleted: " + key)
同样是基于url的md5散列去取cache的key 进行删除。
网友评论