如何清除使用Django的page_cache装饰器时的整个缓存?

37 投票
4 回答
103617 浏览
提问于 2025-04-16 18:30

我有一个比较简单的网站,里面用到了 page_cache 这个装饰器。我设置了一个定时任务(cronjob),它会定期检查是否有新数据,如果有的话就处理这些数据。(这个任务是通过管理命令和 crontab 来执行的)

我想在处理完新数据后,清空所有的页面缓存。

我在这里查看了文档:https://docs.djangoproject.com/en/stable/topics/cache/

我发现了 cache.clear(),看起来正是我需要的功能。我在数据处理的部分添加了一个标志,当找到新数据时就执行 cache.clear()

但是,命令执行后,缓存并没有被清空。(我已经清除了浏览器的缓存,确认不是浏览器的问题)

难道 cache.clear() 不能清除所有的缓存页面吗?

我使用的是 DatabaseCache,所以我想我可以手动去清空缓存表,但有没有更好的方法呢?

4 个回答

4

先把一些东西放进缓存里,然后试着在 manage.py shell 控制台里调用 cache.clear(),然后手动检查一下数据库里的缓存内容。如果这样能成功,那可能是因为你在找到新数据时没有调用 cache.clear()

想要更好地理解这个过程,可以在 cache.clear() 函数的开头加上 import pdb; pdb.set_trace(),然后运行调试服务器,等着看。当有代码调用这个函数时,你就可以一步一步地执行它的代码,或者你会发现这个函数根本没有按你预期被调用。

6

这是一个错误,具体可以查看#19896,在1.6版本中似乎已经修复了。

如果你正在使用旧版本,可以尝试下面的做法,这样可以确保功能正常。

from django.db import router, transaction


def clear_cache(the_cache):
    the_cache.clear()
    # commit the transaction
    db = router.db_for_write(the_cache.cache_model_class)
    transaction.commit_unless_managed(using=db)

这段代码的作用就是确保事务被提交。

33

我遇到了一个关于SQLite数据库缓存的问题——虽然在MySQL数据库缓存中,clear()方法可以正常清除缓存,但在SQLite中却不行。看起来在执行DELETE from [table]语句后,需要调用django.db.transation.commit_unless_managed()才能清除缓存。

在1.3版本之前,我就开始使用多个缓存了,当时还没有官方支持,所以我为一些缓存调用(包括clear())写了一个封装器,这样我就可以重写这个方法并加入commit_unless_managed()。我觉得这可能应该记录为一个bug。

下面是我用来清空memcache缓存(在django.core.cache中是默认缓存)和存储在settings.DATABASES['cache_database']数据库的cache_table中的数据库缓存的代码大纲。

from django.db import connections, transaction
from django.core.cache import cache # This is the memcache cache.

def flush():
    # This works as advertised on the memcached cache:
    cache.clear()
    # This manually purges the SQLite cache:
    cursor = connections['cache_database'].cursor()
    cursor.execute('DELETE FROM cache_table')
    transaction.commit_unless_managed(using='cache_database')

与其懒惰地硬编码,不如从settings.CACHESdjango.db.router中获取值,这样应该会简单很多。

撰写回答