当前位置:  开发笔记 > 编程语言 > 正文

在Django中过期视图缓存?

如何解决《在Django中过期视图缓存?》经验,为你挑选了6个好方法。

@cache_page decorator真棒.但对于我的博客,我想在缓存中保留一个页面,直到有人对帖子发表评论.这听起来像个好主意,因为人们很少发表评论,因此将页面保留在memcached中,而没有人评论会很好.我以为某人之前一定有过这个问题?这与每个网址的缓存不同.

所以我想到的解决方案是:

@cache_page( 60 * 15, "blog" );
def blog( request ) ...

然后我会保留用于博客视图的所有缓存密钥的列表,然后让"博客"缓存空间到期.但是我对Django没有超级经验,所以我想知道是否有人知道更好的方法吗?



1> mazelife..:

此解决方案适用于1.7之前的django版本

这是我写的一个解决方案,用于完成您在我自己的一些项目中所讨论的内容:

def expire_view_cache(view_name, args=[], namespace=None, key_prefix=None):
    """
    This function allows you to invalidate any view-level cache. 
        view_name: view function you wish to invalidate or it's named url pattern
        args: any arguments passed to the view function
        namepace: optioal, if an application namespace is needed
        key prefix: for the @cache_page decorator for the function (if any)
    """
    from django.core.urlresolvers import reverse
    from django.http import HttpRequest
    from django.utils.cache import get_cache_key
    from django.core.cache import cache
    # create a fake request object
    request = HttpRequest()
    # Loookup the request path:
    if namespace:
        view_name = namespace + ":" + view_name
    request.path = reverse(view_name, args=args)
    # get cache key, expire if the cached item exists:
    key = get_cache_key(request, key_prefix=key_prefix)
    if key:
        if cache.get(key):
            # Delete the cache entry.  
            #
            # Note that there is a possible race condition here, as another 
            # process / thread may have refreshed the cache between
            # the call to cache.get() above, and the cache.set(key, None) 
            # below.  This may lead to unexpected performance problems under 
            # severe load.
            cache.set(key, None, 0)
        return True
    return False

Django键入了视图请求的这些缓存,因此它的作用是为缓存视图创建一个伪请求对象,使用它来获取缓存键,然后使其过期.

要按照您所说的方式使用它,请尝试以下方法:

from django.db.models.signals import post_save
from blog.models import Entry

def invalidate_blog_index(sender, **kwargs):
    expire_view_cache("blog")

post_save.connect(invalidate_portfolio_index, sender=Entry)

所以基本上,当保存博客Entry对象时,会调用invalidate_blog_index并且缓存的视图已过期.注意:没有对此进行过广泛的测试,但到目前为止它对我来说还算不错.


我认为参数列表中的args = []是危险的吗?试试这个`def my_func(args = []):args.append('a')在xrange(5)中为我返回args:print my_func()`

2> 小智..:

我为这种情况编写了Django-groupcache(你可以在这里下载代码).在你的情况下,你可以写:

from groupcache.decorators import cache_tagged_page

@cache_tagged_page("blog", 60 * 15)
def blog(request):
    ...

从那里,您可以稍后再做:

from groupcache.utils import uncache_from_tag

# Uncache all view responses tagged as "blog"
uncache_from_tag("blog") 

看看cache_page_against_model():它稍微涉及一些,但它允许你根据模型实体的变化自动解除响应.



3> nesdis..:

使用最新版本的Django(> = 2.0),您正在寻找的内容非常容易实现:

from django.utils.cache import learn_cache_key
from django.core.cache import cache
from django.views.decorators.cache import cache_page

keys = set()

@cache_page( 60 * 15, "blog" );
def blog( request ):
    response = render(request, 'template')
    keys.add(learn_cache_key(request, response)
    return response

def invalidate_cache()
    cache.delete_many(keys)

当有人通过pre_save信号更新博客中的帖子时,您可以将invalidate_cache注册为回调.



4> stefanw..:

cache_page装饰器最后将使用CacheMiddleware,它将根据请求(查看django.utils.cache.get_cache_key)和key_prefix(在您的情况下为"blog")生成缓存键.请注意,"blog"只是一个前缀,而不是整个缓存键.

保存注释后,您可以通过django的post_save信号收到通知,然后您可以尝试为相应的页面构建缓存键,最后说cache.delete(key).

但是,这需要cache_key,它是使用先前缓存的视图的请求构造的.保存注释时,此请求对象不可用.您可以在没有正确请求对象的情况下构造缓存键,但是此构造发生在标记为private(_generate_cache_header_key)的函数中,因此您不应该直接使用此函数.但是,您可以构建一个对象,其路径属性与原始缓存视图相同,Django不会注意到,但我不建议这样做.

cache_page装饰器为您提取了相当多的缓存,并且很难直接删除某个缓存对象.你可以用相同的方式组成自己的键并处理它们,但是这需要更多的编程,并不像cache_page装饰器那样抽象.

当您的注释显示在多个视图中时,您还必须删除多个缓存对象(即带有注释计数的索引页和单个博客条目页).

总结一下:Django为你做了基于时间的缓存密钥到期,但是在适当的时候自定义删除缓存密钥更加棘手.



5> maikelpac..:

这不适用于django 1.7; 你可以在这里看到https://docs.djangoproject.com/en/dev/releases/1.7/#cache-keys-are-now-generated-from-the-request-s-absolute-url新的缓存密钥是使用完整的URL生成,因此仅路径的虚假请求将不起作用.您必须正确设置请求主机值.

fake_meta = {'HTTP_HOST':'myhost',}
request.META = fake_meta

如果您有多个域使用相同的视图,您应该在HTTP_HOST中循环它们,获取正确的密钥并为每个域执行清理.



6> Duncan..:

Django查看v1.7及更高版本的缓存失效.在Django 1.9上测试过.

def invalidate_cache(path=''):
    ''' this function uses Django's caching function get_cache_key(). Since 1.7, 
        Django has used more variables from the request object (scheme, host, 
        path, and query string) in order to create the MD5 hashed part of the
        cache_key. Additionally, Django will use your server's timezone and 
        language as properties as well. If internationalization is important to
        your application, you will most likely need to adapt this function to
        handle that appropriately.
    '''
    from django.core.cache import cache
    from django.http import HttpRequest
    from django.utils.cache import get_cache_key

    # Bootstrap request:
    #   request.path should point to the view endpoint you want to invalidate
    #   request.META must include the correct SERVER_NAME and SERVER_PORT as django uses these in order
    #   to build a MD5 hashed value for the cache_key. Similarly, we need to artificially set the 
    #   language code on the request to 'en-us' to match the initial creation of the cache_key. 
    #   YMMV regarding the language code.        
    request = HttpRequest()
    request.META = {'SERVER_NAME':'localhost','SERVER_PORT':8000}
    request.LANGUAGE_CODE = 'en-us'
    request.path = path

    try:
        cache_key = get_cache_key(request)
        if cache_key :
            if cache.has_key(cache_key):
                cache.delete(cache_key)
                return (True, 'successfully invalidated')
            else:
                return (False, 'cache_key does not exist in cache')
        else:
            raise ValueError('failed to create cache_key')
    except (ValueError, Exception) as e:            
        return (False, e)

用法:

status, message = invalidate_cache(path='/api/v1/blog/')

推荐阅读
携手相约幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有