美文网首页python programming
django 站点级缓存模式下定向清除指定页面的缓存

django 站点级缓存模式下定向清除指定页面的缓存

作者: pygogogo | 来源:发表于2017-10-26 11:36 被阅读0次

一. 站点级缓存模式的设置

需要把'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 进行删除。

相关文章

网友评论

    本文标题:django 站点级缓存模式下定向清除指定页面的缓存

    本文链接:https://www.haomeiwen.com/subject/eibhpxtx.html