如何强制Jinja2模板重新编译?
我想在Django应用中切换Jinja2模板,而不需要重启应用。
有没有人做过这个?基本上,我需要在更改皮肤选择后强制Jinja2重新加载模板。
我试过在模板环境对象上重新创建缓存对象,但没有效果。
myskin_utils.py:
from jinja2.environment import create_cache
ENV_OBJECT.cache = create_cache(50)
我也尝试过重新加载包含我的ENV_OBJECT的模块,使用的是
reload(myskin) #also no effect on the output
还有一件我想动态更改的事情是语言,但我想这可能是个单独的问题。
谢谢任何建议。
编辑:我没有为Jinja2设置缓存,但我确实发现从Django模板切换到Jinja后速度变快了。我怀疑模板的字节码存储在我视图函数的编译代码中,但我没有深入研究Jinja的细节。
我在视图模块的全局命名空间中导入了ENV(一个继承自Jinja的Environment
的CoffinEnvironment
实例),并在视图函数中调用ENV.get_template()
(Django+Coffin+Jinja2)。
我发现如果在视图函数中对我的环境模块调用Python的reload()
内置函数,模板确实会切换,但我不想把这段代码放到每个函数里。
2 个回答
这个说法不对。Jinja 默认使用内存中的 LRUCache 来缓存,缓存的大小由 Environment 参数决定。你还可以使用磁盘缓存,这样在应用程序重新启动时也能保持良好的性能(不需要重新编译)。
默认情况下,Jinja2并不使用任何缓存,但建议配置一个缓存系统来加快速度。这样,Jinja2就不需要在每次请求时都解析和编译每个模板。目前,Jinja2支持两种不同的缓存类型:
其中一种是 FileSystemBytecodeCache
,顾名思义,它是基于文件的。这意味着所有编译好的模板都会存储在文件系统中,并从那里读取。如果你仔细看这个实现,你会发现有一个 cache.clear()
方法,它会简单地删除这个临时文件夹中的所有文件。这会导致所有模板再次被解析和编译。
另一种缓存类型叫做 MemcachedBytecodeCache
,它是Memcache的一个简单封装。这个方法更推荐,因为Memcache把所有东西都存储在内存中,所以比从硬盘读取要快一些,而且你可以从不同的主机使用同一个缓存(这在你运行集群时很有用)。
底层的Memcache客户端(可以是werkzeug.contrib.cache、python-memcached或cmemcache)也提供了一个 clear()
方法,可以删除缓存中的所有内容。但因为你可能还会用缓存来存储其他东西(比如存储一些耗时的数据库查询结果),所以在Jinja中并没有暴露这个 clear()
方法,因为这样会影响到所有内容,而不仅仅是模板。
所以,总结一下,你的选择有:
- 不使用缓存的Jinja2
- 使用带有
FileSystemBytecodeCache
的Jinja2,并调用cache.clear()
- 使用带有
MemcachedBytecodeCache
的Jinja2,并调用memcache_client.clear()
(这会清除缓存中的所有内容)。 - 在另一个端口运行一个单独的memcached进程,仅用于Jinja2。然后调用
memcache_client.clear()
,这样所有模板都会被清除。