在 bottle.py 中禁用 Jinja2 模板缓存的最佳方法是啥?
Posted
技术标签:
【中文标题】在 bottle.py 中禁用 Jinja2 模板缓存的最佳方法是啥?【英文标题】:What's the best way to disable Jinja2 template caching in bottle.py?在 bottle.py 中禁用 Jinja2 模板缓存的最佳方法是什么? 【发布时间】:2012-01-26 09:09:57 【问题描述】:我将 Jinja2 模板与 Bottle.py 和 Google App Engine 的 dev_appserver 一起用于开发。我希望模板在每个请求时自动重新加载(或者理想情况下仅在它们更改时),这样我就不必不断重新启动服务器。
根据瓶子的文档,您应该能够通过调用 bottle.debug(True)
来禁用模板缓存。
不过,Jinja 似乎仍在缓存其模板。我相信这是因为瓶子 jinja2 适配器的编写方式(它只是使用默认的 Jinja2 加载器,并没有公开很多配置选项)。
在Jinja2 Docs 之后,我编写了这个自定义加载器,我希望每次都会触发模板重新加载,但它似乎也不起作用:
import settings
from bottle import jinja2_template
from bottle import Jinja2Template, template as base_template
class AutoreloadJinja2Template(Jinja2Template):
def loader(self, name):
def uptodate():
# Always reload the template if we're in DEVMODE (a boolean flag)
return not settings.DEVMODE
fname = self.search(name, self.lookup)
if fname:
with open(fname, "rb") as f:
source = f.read().decode(self.encoding)
return (source, fname, uptodate)
template = functools.partial(base_template,
template_adapter=AutoreloadJinja2Template,
template_lookup = settings.TEMPLATE_PATHS,
template_settings=
'auto_reload': settings.DEVMODE
)
在我重新启动 dev_appserver 之前,模板仍在缓存中。这一定是一个相当普遍的问题。有没有人有可行的解决方案?
更新:
我最终做了类似的事情:
class CustomJinja2Template(Jinja2Template):
if settings.DEVMODE:
def prepare(self, *args, **kwargs):
kwargs.update('cache_size':0)
return Jinja2Template.prepare(self, *args, **kwargs)
template = functools.partial(original_template, template_adapter=CustomJinja2Template)
这会导致模板始终重新加载,但前提是已触及 python 模块。即,如果您只是编辑模板文件,则更改不会生效,直到您编辑导入它的 python 文件之一。似乎模板仍在某处缓存。
【问题讨论】:
【参考方案1】:我通过完全放弃瓶子的模板解决方案并使用纯 jinja2 解决了这个问题。似乎只有Jijnja 的FileSystemLoader
可以监视文件更改。
我定义了新的template
函数如下(它在views/
中查找文件,就像以前的瓶子一样):
from jinja2 import Environment, FileSystemLoader
if local_settings.DEBUG:
jinja2_env = Environment(loader=FileSystemLoader('views/'), cache_size=0)
else:
jinja2_env = Environment(loader=FileSystemLoader('views/'))
def template(name, ctx):
t = jinja2_env.get_template(name)
return t.render(**ctx)
然后我这样使用它:
@route('/hello')
def hello():
return template('index.tpl', 'text': "hello")
与 Bottle API 的不同之处在于您必须在文件名中包含.tpl
,并且您必须将上下文变量作为字典传递。
【讨论】:
【参考方案2】:Bottle 在内部缓存模板(独立于 Jinja2 缓存)。您可以通过bottle.debug(True)
或bottle.run(..., debug=True)
禁用缓存或通过bottle.TEMPLATES.clear()
清除缓存。
【讨论】:
感谢您的回复。我不知道bottle.TEMPLATES.clear(),它可以派上用场!我从项目一开始就设置了 bottle.debug(True),所以我很确定这是配置 Jinja 缓存的问题。 让我绊倒的是在bottle.run之前运行bottle.debug(True)。 bottle.run 的 debug 参数的默认值为 False,如果未指定,则会覆盖 bottle.DEBUG。【参考方案3】:使用瓶子视图装饰器,你可以做到@view('your_view', cache_size=0)
。
Bottle 在服务器适配器中有一个reloader=True
参数,但我猜它只适用于 SimpleTemplate。我会尝试将此行为扩展到其他模板引擎。
如果您想在所有视图中都这样做,也许您可以这样做:
import functools
view = functools.partials(view, cache_size=0)
这样,只有在调试模式下才能执行此操作,向此代码 if bottle.DEBUG
添加 if 语句。
【讨论】:
向下箭头是因为 cache_size=0 参数对我使用 view() 装饰器或 template() 函数不起作用。同样run(reloader=True)会抛出错误:“local variable 'lockfile' referenced before assignment” @arkancisscan 这个错误可能与我的 responseq 无关,但没关系。只是告诉你,我将你的评论作为问题报告给瓶 (github.com/defnull/bottle/issues/278)。您能否提供有关 github 中错误的更多详细信息?您使用的是哪个服务器适配器?谢谢! @iurisilvio 感谢您的尝试!【参考方案4】:jinja2 中的Environment 对象具有缓存大小的配置值,根据文档,
如果缓存大小设置为 0,模板会一直重新编译
你尝试过这样的事情吗?
from jinja2 import Environment
env = Environment(cache_size=0)
【讨论】:
以上是关于在 bottle.py 中禁用 Jinja2 模板缓存的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章