在Django中清除特定缓存

29 投票
5 回答
44604 浏览
提问于 2025-04-17 09:50

我在做一个django项目,使用了视图缓存。

它说缓存是用网址作为关键字的,所以我在想,如果用户更新或删除了某个对象,怎么清除其中一个关键字的缓存。

举个例子:用户在 domain.com/post/1234/ 上发布了一篇博客。如果用户对这篇文章进行了编辑,我想在保存编辑后的文章时,添加一个命令来删除这个网址的缓存版本。

我现在用的是:

@cache_page(60 * 60)
def post_page(....):

如果帖子ID是1234,似乎这样可以工作,但实际上并没有:

def edit_post(....):
    # stuff that saves the edits
    cache.delete('/post/%s/' % post.id)
    return Http.....

5 个回答

1

我写了一个函数,用来删除以某些文本开头的键。这可以帮助我删除动态生成的键。

列出缓存的帖子

def get_posts(tag, page=1):
    cached_data = cache.get('list_posts_home_tag%s_page%s' % (tag, page))
    if not cached_data:
        cached_data = mycontroller.get_posts(tag, page)
        cache.set('list_posts_home_tag%s_page%s' % (tag, page), cached_data, 60)
    return cached_data

每当更新任何帖子时,调用 flush_cache

def update(data):
    response = mycontroller.update(data)
    flush_cache('list_posts_home')
    return response

使用 flush_cache 来删除任何动态缓存

def flush_cache(text):
    for key in list(cache._cache.keys()):
        if text in key:
            cache.delete(key.replace(':1:', ''))

别忘了从 Django 导入缓存

from django.core.cache import cache
2

我之前也遇到过同样的问题,后来找到了这个解决办法。

如果你在使用这个装饰器:

django.views.decorators.cache.cache_page

你可以使用这个函数:

import hashlib
from typing import List
from django.core.cache import cache


def get_cache_keys_from_url(absolute_uri) -> List[str]:
    url = hashlib.md5(f"absolute_uri".encode('ascii'))
    return cache.keys(f'*{url.hexdigest()}*')

这个函数是用来获取 absolute_uri 的缓存键的。

然后你可以用 cache.delete_many(get_cache_keys_from_url(http://exemple.com/post/1234/)) 来清除这个网址的页面缓存 - http://exemple.com/post/1234/

34

根据Django缓存文档,使用cache.delete('key')应该就可以了。所以,我想到你可能会遇到两个问题:

  1. 你的导入可能不正确,记得你需要从django.core.cache模块导入cache

    from django.core.cache import cache
    
    # ...
    cache.delete('my_url')
    
  2. 你使用的键可能不对(可能是用了完整的URL,包括“domain.com”)。要检查确切的URL,你可以进入你的命令行:

    $ ./manage.py shell
    >>> from django.core.cache import cache
    >>> cache.has_key('/post/1234/')
    # this will return True or False, whether the key was found or not
    # if False, keep trying until you find the correct key ...
    >>> cache.has_key('domain.com/post/1234/') # including domain.com ?
    >>> cache.has_key('www.domain.com/post/1234/') # including www.domain.com ?
    >>> cache.has_key('/post/1234') # without the trailing / ?
    

撰写回答