Django使用特定的key_prefix删除缓存

Wes*_*ssi 5 python django django-cache django-views python-3.x

我正在使用Django的每视图@cache_page装饰器,并key_prefix为每个视图设置了不同的.

我之前删除了缓存:

from django.core.cache import cache
cache.clear()
Run Code Online (Sandbox Code Playgroud)

但是,如果我只想删除包含特定的键key_prefix呢?我显然可以通过连接到数据库并使用原始sql删除,但我想知道它是否可以用'纯'Django完成?

我正在使用数据库缓存,而不是内存缓存.

我正在使用Django 1.11和Python 3.6

Soy*_*ulu 12

我用这样的代码实现了我想要的:

# first: pip install django-redis

from django.core.cache import cache

cache.delete_many(keys=cache.keys('*.letters.*'))
Run Code Online (Sandbox Code Playgroud)

它删除所有键包含“字母”的缓存。

编辑:我使用redis服务器。我没有针对其他缓存服务器进行测试。


e4c*_*4c5 7

太长了cache.delete以及cache.delete_many您可以选择的选项。

长答案。 @cache_page被高估了。当你使用这个装饰器时,你经常会发现缓存总是包含比你预期更多的缓存条目。您最终想要删除一大堆缓存条目。这似乎正是这里发生的事情。

我使用的是数据库缓存,而不是内存缓存。

使用缓存的主要思想之一是减少服务器上的负载,另一个是减少昂贵的计算或数据库查询。但实际上很多网页并没有昂贵的计算。大多数缓慢的查询可以通过仔细选择索引来优化。

如果数据库本身就是该缓存,那么您就不会减少数据库的负载。如果您需要为不同的用户显示不同的内容怎么办?这件事非常复杂。

如果我只想删除包含特定 key_prefix 的密钥怎么办?

考虑使用redis。这是 django 中最好的缓存后端之一(作为第三方模块)。能够在单个命令中删除多个键是 Redis 的众多有用功能之一。

  • “如果数据库本身就是缓存,那么您就不会减少数据库的负载。” 我强烈不同意这一点。如果生成一个复杂列表需要 60 秒和 10,000 个查询,并且将其缓存在数据库中,则可以通过一个查询在 0.1 秒内检索它。通过数据库缓存可以“大大”减少数据库负载,而无需使用 Redis。这就是它存在的原因。 (2认同)

Tar*_*ani 6

由于@ e4c5提到的缓存用于快速的东西,你应该使用redis.但既然你的问题是关于数据库我会回答相同的问题.

在Django中没有现成的功能.但是,python的最佳部分是你可以轻松地添加新功能.以下是我创建的测试请求

def index(request):
    cache.set("name", "tarun")
    cache.set("name_1", "tarun")
    cache.set("name2", "tarun")
    cache.set("name_4", "tarun")
    cache.set("nam", "tarun")

    cache.clear(prefix="name")
    nam = cache.get("nam")
    name_4 = cache.get("name_4", default="deleted")
    return HttpResponse("Hello, world. nam={nam}, name_4={name_4}".format(nam=nam, name_4=name_4))
Run Code Online (Sandbox Code Playgroud)

修补

要获得prefix在某些地方添加下面的补丁代码所需的功能.我settings.py这样用过

original_clear = None


def patch_clear():
    from django.db import connections, router
    from django.core.cache.backends.db import DatabaseCache

    def __clear(self, prefix=None, version=None):
        db = router.db_for_write(self.cache_model_class)
        connection = connections[db]
        table = connection.ops.quote_name(self._table)
        with connection.cursor() as cursor:
            if prefix is None:
                cursor.execute('DELETE FROM %s ' % table)
            else:
                prefix = self.make_key(prefix, version)
                cursor.execute("DELETE FROM %s where cache_key like '%s%%'" % (table, prefix))

    global original_clear
    original_clear = DatabaseCache.clear
    DatabaseCache.clear = __clear

patch_clear()
Run Code Online (Sandbox Code Playgroud)