美文网首页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