10

我将 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 文件之一。似乎模板仍在某处缓存。

4

4 回答 4

6

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

于 2012-02-02T13:03:41.447 回答
6

我通过完全放弃瓶子的模板解决方案并使用纯 jinja2 解决了这个问题。似乎JijnjaFileSystemLoader是唯一可以监视文件更改的。

我定义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"})

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

于 2012-02-22T13:17:24.177 回答
3

jinja2 中的Environment对象具有缓存大小的配置值,根据文档,

如果缓存大小设置为 0,模板会一直重新编译

你有没有尝试过这样的事情?

from jinja2 import Environment
env = Environment(cache_size=0)
于 2011-12-22T20:33:46.793 回答
1

使用瓶子视图装饰器,你可以做到@view('your_view', cache_size=0)

Bottlereloader=True在服务器适配器中有一个参数,但我猜它只适用于 SimpleTemplate。我将尝试将此行为扩展到其他模板引擎。

如果您想在所有视图中执行此操作,也许您可​​以执行以下操作:

import functools
view = functools.partials(view, cache_size=0)

这样,您只能在调试模式下向此代码添加 if 语句时执行此操作if bottle.DEBUG

于 2011-12-25T13:31:00.067 回答