在bottle.py中禁用Jinja2模板缓存的最佳方法是什么?

let*_*ted 9 python jinja2 bottle

我正在使用带有Bottle.py和Google App Engine的dev_appserver的Jinja2模板进行开发.我希望模板能够在每个请求上自动重新加载(或者理想情况下只在它们发生更改时),这样我就不必继续重新启动服务器了.

根据瓶子的文档,你应该能够通过调用来禁用模板缓存bottle.debug(True).

不过,Jinja似乎仍在缓存其模板.我相信这是因为瓶子jinja2适配器的编写方式(它只使用默认的Jinja2加载器,并没有暴露许多配置选项).

Jinja2文档之后,我编写了这个自定义Loader,我希望每次都能触发模板重新加载,但它似乎也不起作用:

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
    }
)
Run Code Online (Sandbox Code Playgroud)

在重新启动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)
Run Code Online (Sandbox Code Playgroud)

这会导致模板始终重新加载,但仅在触摸了python模块时才会重新加载.即,如果您只是编辑模板文件,则在您编辑导入它的某个python文件之前,更改不会生效.似乎模板仍在某处缓存.

小智 6

我通过完全抛弃瓶子的模板解决方案并使用纯粹的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)
Run Code Online (Sandbox Code Playgroud)

然后我像这样使用它:

@route('/hello')
def hello():
    return template('index.tpl', {'text': "hello"})
Run Code Online (Sandbox Code Playgroud)

与瓶子API的不同之处在于您必须包含.tpl在文件名中,并且必须将上下文变量作为字典传递.


def*_*ull 5

Bottle内部缓存模板(独立于Jinja2缓存).您可以通过bottle.debug(True)或禁用缓存,bottle.run(..., debug=True)或清除缓存bottle.TEMPLATES.clear().