一尘不染

使Django中的视图缓存过期?

django

@cache_page decorator真棒。但是对于我的博客,我希望将页面保留在缓存中,直到有人发表评论。这听起来像是一个好主意,因为人们很少评论,因此将页面保留在内存缓存中,而没人评论会很好。我以为有人以前一定有这个问题?这与每个URL的缓存不同。

因此,我正在考虑的解决方案是:

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

然后,我将保留用于博客视图的所有缓存键的列表,然后使“博客”缓存空间过期。但是我对Django并没有超级的经验,所以我想知道是否有人知道这样做的更好方法?


阅读 339

收藏
2020-03-26

共1个答案

一尘不染

此解决方案适用于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)

因此,基本上,只要保存了Blog Entry对象,就会调用invalidate_blog_index,并且缓存的视图也会过期。注意:尚未对此进行广泛测试,但到目前为止对我来说还不错。

2020-03-26