模板片段缓存似乎对某些自定义模板标签无效
我在我的Django应用中实现了缓存,使用了按视图缓存和模板片段缓存。在我的某些页面上,我使用了一个自定义的Django模板标签,这个标签是由第三方开发者提供的。它在模板标签中接收一些参数,然后向一个远程服务器发送请求,获取XML格式的响应,最后将结果渲染到我的页面上。
我觉得可以很简单地使用片段缓存来缓存这个内容,于是我这样做了:
{% load cache %}
{% cache 500 request.user.username %}
{% load third party custom tags %}
{% expensive custom tag set that gets stuff from a third party server via xml %}
{{ some.stuff}}
{% endcache %}
问题是,不管我怎么做,请求还是会发送到那个远程服务器,Django似乎不喜欢缓存这些自定义的模板标签。我知道memcached在其他视图和模板中工作得很好,一切都正常。难道我做的事情和片段缓存不兼容吗?有没有什么解决办法?
4 个回答
我觉得这跟自定义标签没什么关系。
我们最终重写了Django的缓存标签,因为我们需要比原来的标签更多的控制权。你可以自己复制一份,然后加一些调试用的打印语句进去。特别是,检查一下文件名(假设你是把缓存存到文件里的),看看生成了什么。可能是文件名在不该变化的时候变了,这样就会导致每次都需要重新渲染里面的内容。
去看看django/templatetags/cache.py文件。这个文件只有63行代码。
你有没有试过给缓存片段换个名字?使用request.user.username可能会有几个问题:
如果用户没有登录,request.user.username可能是空的,这样就会导致缓存片段没有名字。
如果用户已经登录,这个调用会每3分钟对每个用户至少执行一次第三方模板标签。
也许可以尝试把缓存片段的名字改一下来测试一下:
{% cache 500 customxml %}
我还建议把第三方模板标签放到缓存标签外面加载,像这样:
{% load cache third_party_custom_tags %}
{% cache 500 request.user.username %}
{% expensive custom tag set that gets stuff from a third party server via xml %}
{{ some.stuff}}
{% endcache %}
我不太确定缓存框架是否会缓存模板标签的结果。如果这样不行,我会看看这个模板标签背后是怎么工作的,然后用Django的低级缓存重新实现这个模板标签。
如果你想要缓存的模板片段不能被“腌制”(也就是不能被保存成一种特定的格式),那么memcached就无法存储它,并且会抛出一个错误。从我了解到的情况来看,在渲染Django模板时产生的错误是被隐藏起来的。因为你的自定义标签在进行HTTP请求,所以可能有一些socket对象(这些是不能被“腌制”的)以某种方式被存储到了模板片段中。
如果真是这样,我能想到的解决办法就是修改这个自定义标签,去掉任何多余的socket对象。