枚举Django数据库缓存中的键

时间:2016-06-03 18:41:55

标签: python django caching django-1.8

我正在使用Django数据库缓存(https://docs.djangoproject.com/en/1.8/topics/cache/#database-caching)在Django应用程序中缓存一些计算结果。

在给定时刻枚举存储在缓存中的所有密钥的方法是什么。偶尔我需要在到期前使​​缓存部分无效(删除)(因为我正在调试)。缓存键是通过精心计算生成的,我不想重复该计算。我知道我想删除的缓存键的前缀,但我不知道完整的键字符串。

我没有立即看到缓存API我怎么能这样做。我可以获取条目,创建密钥,删除条目并清除整个缓存:https://docs.djangoproject.com/en/1.8/topics/cache/#the-low-level-cache-api

现在我必须使用SQL语句提取密钥,这是一个PITA。我想编写一个管理命令,我可以使用它来使部分无效。

示例:

settings.py:

CACHES = {
    'default': {
         'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
         'LOCATION': 'default-cache',
    },
    'staticfiles': {
         'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
         'LOCATION': 'static-files',
    },
    'bla_stats': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'django_bla_stats_cache',
    }
}

我按照我链接的Django文档中的说明创建了缓存。将一些数据放入缓存(没有过期:我控制条目)。

from django.core.cache import caches

cache = caches['bla_stats']
cache.set("a_d3e6a1e1-0565-4d20-8887-4fda47186299", "foo", None)
cache.set("a_e79a1e0d-bfe1-4a04-8db3-42495c09e780", "bar", None)
cache.set("b_390d42ec-2b70-436d-8600-404034b07fe9", "fiz", None)
cache.set("b_a2d3cb52-8941-4812-8186-676ee3de0ec3", "baz", None)

以下是问题:如何在任何给定时刻找到缓存中具有密钥前缀“b_”的所有密钥?

2 个答案:

答案 0 :(得分:2)

假设您使用MySQL作为数据库后端,DatabaseCache的这个子类应该可以在缓存键上返回LIKE类型查询的所有结果的字典。

class DatabaseCacheExtended(DatabaseCache):
    def get_where(self, query, default=None, version=None):
        db = router.db_for_read(self.cache_model_class)
        table = connections[db].ops.quote_name(self._table)

        with connections[db].cursor() as cursor:
            cursor.execute("SELECT cache_key, value, expires FROM %s "
                           "WHERE cache_key LIKE %%s" % table, [query])
            rows = cursor.fetchall()
        if len(rows) < 1:
            return {}
        return_d ={}
        for row in rows:
            value = connections[db].ops.process_clob(row[1])
            return_d[row[0]] = pickle.loads(base64.b64decode(force_bytes(value)))
        return return_d

然后您只需要在settings.py

中更改已注册的后端
    'bla_stats': {
        'BACKEND': 'path.to.DatabaseCacheExtended',
        'LOCATION': 'django_bla_stats_cache',
     }

示例:

>>> from django.core.cache import caches
>>> cache = caches['bla_stats']
>>> cache.get_where("b_%")
... {"b_key1":"val1", "b_key2":"val2"}

答案 1 :(得分:1)

Django的缓存API不能提供你想要的东西,所以没有任何实现。一种解决方案是创建自己的后端。

您仍然需要解决一些SQL查询问题,但您可以继承ATSL link来创建自己的自定义后端。添加一个方法,允许您通过前缀查询键,或通过前缀删除,然后将其包装到管理命令中以便于访问。