如何在Django中缓存查询结果?
我在我的Django应用中尝试缓存查询结果。但是,似乎它把整个应用都缓存了。我尝试了以下逻辑:
def cacheView():
result = cache.get('key')
if result is None:
result = Model.objects.get(id=1)
cache.set('key', 'result')
我在用户登录时调用这个方法。但是,如果我在登录后尝试注销,它却让我停留在同一页面,好像我仍然登录着。我试着按照Django的文档来处理缓存,链接是 http://docs.djangoproject.com/en/1.2/topics/cache/,但没有成功。
我还尝试了另一种方法,就是在视图函数上方使用缓存装饰器,像这样:
@cache_control(max_age=1000)
def cacheView():
...
但这样会出现一个错误,提示“响应头未定义”。我对Django还很陌生,肯定是漏掉了什么。有没有什么建议?
2 个回答
从你的例子来看,不太清楚为什么注销会失败,但这应该和缓存模型没有关系(除非你在缓存用户模型,并且用缓存的用户来进行身份验证,而不是用请求中的用户?)
你使用cache.get和cache.set的方式是可以的(set会在键不存在时创建一个新键)。
缓存查询可能会比较复杂,因为当数据发生变化时,你需要处理缓存失效的问题,以免返回过时的结果。
可以看看这些针对Django的查询缓存库,它们旨在简化这个过程:
看一下官方的Django文档吧:缓存和查询集
每个查询集(QuerySet)都有一个缓存,用来减少对数据库的访问。 (...)
还有:
在新创建的查询集中,缓存是空的。第一次评估查询集时,也就是第一次进行数据库查询时,Django会把查询结果保存在查询集的缓存中,并返回你明确请求的结果(比如,如果你在遍历查询集,就返回下一个元素)。之后再评估这个查询集时,就会使用缓存中的结果。
对于查询集来说,缓存是自动完成的(也就是查询的结果会被缓存)。
补充:
关于你在问题中贴的代码。如果缓存中还没有这个键,你需要用add()
方法来创建它,但要记住,默认情况下它会在30秒后过期。如果你想让它保存更久,就需要在add()/set()
方法中添加超时选项。
如果你想为整个网站进行缓存(比如你用的装饰器),你需要在settings.py中的MIDDLEWARE_CLASSES
里添加合适的中间件(要按这个顺序添加,因为中间件的顺序很重要,它们会按照你定义的顺序一个一个加载):
MIDDLEWARE_CLASSES = (
# ...
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
# ...
)
如果你没有这些设置,每次使用全站缓存功能时都会收到错误的头信息。