在Django中处理memcache缓存的模式

4 投票
2 回答
1044 浏览
提问于 2025-04-15 16:40

我有一个很大的Django项目,里面有几个相互关联的项目,并且使用了很多缓存。目前有一个文件专门用来存放缓存的辅助函数。比如说,get_object_x(id)这个函数会先检查缓存中是否有这个对象,如果没有,就去数据库里找,然后把它取出来并返回,同时把它存入缓存。这种模式也适用于缓存一组对象,那个文件还用来处理缓存失效的方法。

不过,现在在不同应用之间的导入上出现了一些问题。应用的模型文件里有一些我们想用缓存的辅助函数,而缓存助手文件显然需要导入模型文件。

所以我想问:有没有更好的方法来处理这个问题,避免出现循环导入的问题(或者说有没有更聪明的解决办法)?理想情况下,我们也希望能以更好的、少一些手动操作的方式来处理缓存失效。我猜使用Django的自定义管理器和信号是个不错的起点,甚至可以完全不需要缓存助手文件,但有没有人有更好的建议或者可以参考的方向呢?

2 个回答

3

既然你提到你在缓存Django的ORM模型实例,可以看看django-orm-cache这个工具。它可以自动帮你缓存模型实例,而且会聪明地判断什么时候需要清除缓存。

你担心的循环导入问题其实没关系——你只需要把需要缓存的模型从ormcache.models.CachedModel这个类继承,而不是从Django的django.db.models.Model继承,这样你就能轻松实现缓存了。

7

避免循环导入的一个通用Python方法是把一部分导入放在依赖的函数内部:

# module_a.py
import module_b

def foo():
    return "bar"

def bar():
    return module_b.baz()

# module_b.py
def baz():
    import module_a
    return module_a.foo()

至于缓存,听起来你需要一个看起来像这样的函数:

def get_cached(model, **kwargs):
    timeout = kwargs.pop('timeout', 60 * 60)
    key = '%s:%s' % (model, kwargs)
    result = cache.get(key)
    if result is None:
        result = model.objects.get(**kwargs)
        cache.set(key, result, timeout)
    return result

现在你不需要为每一个模型创建“getbyid”方法。你可以这样做:

blog_entry = get_cached(BlogEntry, pk = 4)

你也可以写类似的函数来处理完整的查询集,而不仅仅是单个模型对象,使用.get()方法。

撰写回答