Django 删除具有特定 key_prefix 的缓存
Django delete cache with specific key_prefix
我正在使用 Django 的每个视图 @cache_page
装饰器,并为每个视图设置了不同的 key_prefix
。
我之前删除了缓存:
from django.core.cache import cache
cache.clear()
但是如果我只想删除包含特定 key_prefix
的密钥怎么办?我显然可以通过连接到数据库并使用原始 sql 删除来做到这一点,但我想知道是否可以使用 'pure' Django 来完成?
我使用的是数据库缓存,而不是内存缓存。
我正在使用 Django 1.11 和 Python 3.6
TLDR; cache.delete
和 cache.delete_many
是您可用的选项。
长答案。
@cache_page
被高估了。当你使用这个装饰器时,你经常会发现缓存中总是包含比你预期的更多的缓存条目。您最终想要删除一大堆缓存条目。这似乎正是这里发生的事情。
I'm using a database cache, not a memory cache.
使用缓存的主要思想之一是减少服务器上的负载,另一个是减少昂贵的计算或数据库查询。但实际上很多网页并没有昂贵的计算。可以通过仔细选择索引来优化大多数慢速查询。
如果数据库本身就是缓存,那么您并没有减少数据库的负载。如果您需要为不同的用户显示不同的内容怎么办?这变得非常复杂。
what if I just want to delete the keys containing a specific
key_prefix?
考虑使用redis。这是 django 中最好的缓存后端之一(作为第三方模块)。能够在单个命令中删除多个键是redis的众多有用功能之一。
正如@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))
要获得 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()
我用这样的代码实现了我想要的:
cache.delete_many(keys=cache.keys('*.letters.*'))
它删除所有键包含“字母”的缓存。
编辑:
我使用 redis 服务器。我没有对其他缓存服务器进行测试。
我正在使用 Django 的每个视图 @cache_page
装饰器,并为每个视图设置了不同的 key_prefix
。
我之前删除了缓存:
from django.core.cache import cache
cache.clear()
但是如果我只想删除包含特定 key_prefix
的密钥怎么办?我显然可以通过连接到数据库并使用原始 sql 删除来做到这一点,但我想知道是否可以使用 'pure' Django 来完成?
我使用的是数据库缓存,而不是内存缓存。
我正在使用 Django 1.11 和 Python 3.6
TLDR; cache.delete
和 cache.delete_many
是您可用的选项。
长答案。
@cache_page
被高估了。当你使用这个装饰器时,你经常会发现缓存中总是包含比你预期的更多的缓存条目。您最终想要删除一大堆缓存条目。这似乎正是这里发生的事情。
I'm using a database cache, not a memory cache.
使用缓存的主要思想之一是减少服务器上的负载,另一个是减少昂贵的计算或数据库查询。但实际上很多网页并没有昂贵的计算。可以通过仔细选择索引来优化大多数慢速查询。
如果数据库本身就是缓存,那么您并没有减少数据库的负载。如果您需要为不同的用户显示不同的内容怎么办?这变得非常复杂。
what if I just want to delete the keys containing a specific key_prefix?
考虑使用redis。这是 django 中最好的缓存后端之一(作为第三方模块)。能够在单个命令中删除多个键是redis的众多有用功能之一。
正如@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))
要获得 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()
我用这样的代码实现了我想要的:
cache.delete_many(keys=cache.keys('*.letters.*'))
它删除所有键包含“字母”的缓存。
编辑: 我使用 redis 服务器。我没有对其他缓存服务器进行测试。