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

发布于 2024-12-22 16:21:22 字数 1711 浏览 2 评论 0原文

我使用 Jinja2 模板与 Bottle.py 和 Google App Engine 的 dev_appserver 进行开发。我希望模板在每次请求时自动重新加载(或者理想情况下仅在它们发生更改时),这样我就不必不断重新启动服务器。

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

不过,Jinja 似乎仍在缓存其模板。我相信这是因为 Bottle jinja2 适配器的编写方式(它只使用默认的 Jinja2 加载器并且不公开许多配置选项)。

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

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 文件之一之前,更改不会生效。模板似乎仍然缓存在某个地方。

I'm using Jinja2 templates with Bottle.py and Google App Engine's dev_appserver for development. I want the templates to automatically reload on every request (or ideally only when they change), so that I don't have to keep restarting the server.

According to bottle's docs, you're supposed to be able to disable template caching by calling bottle.debug(True).

Jinja still seems to be caching its templates, though. I believe this to be because of the way the bottle jinja2 adapter is written (it just uses a default Jinja2 loader and doesn't expose many configuration options).

Following the Jinja2 Docs, I wrote this custom Loader that I would expect to trigger a template reload every time, but it doesn't seem to work either:

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
    }
)

Templates are still getting cached until I restart dev_appserver. This must be a fairly common problem. Does anyone have a solution that works?

UPDATE:

I ended up doing something like:

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)

This causes the templates to always reload, but only if a python module has been touched. i.e. if you just edit a template file, the changes won't take affect until you edit one of the python files that imports it. It seems as if the templates are still being cached somewhere.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

小糖芽 2024-12-29 16:21:22

我通过完全放弃 Bottle 的模板解决方案并使用纯 jinja2 解决了这个问题。看来 Jijnja 的 FileSystemLoader 是唯一可以监视文件更改的。

我定义了新的 template 函数如下(它在 views/ 中查找文件,就像 Bottle 以前那样):

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 ,并且必须将上下文变量作为字典传递。

I resolved this issue by ditching bottle's template solutions completely and using pure jinja2. It seems that Jijnja's FileSystemLoader is the only one, which can watch for file changes.

I defined new template function as follows (it looks for files in views/, just like bottle used to):

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)

Then I use it like this:

@route('/hello')
def hello():
    return template('index.tpl', {'text': "hello"})

The difference from bottle's API is that you have to include .tpl in file name and you have to pass context variables as dictionary.

把昨日还给我 2024-12-29 16:21:22

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

Bottle caches templates internally (independent from Jinja2 caching). You can disable the cache via bottle.debug(True) or bottle.run(..., debug=True) or clear the cache with bottle.TEMPLATES.clear().

∞梦里开花 2024-12-29 16:21:22

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

如果缓存大小设置为 0,模板将始终重新编译

您尝试过这样的事情吗?

from jinja2 import Environment
env = Environment(cache_size=0)

The Environment object in jinja2 has a configuration value for the cache size and, according to the documentation,

If the cache size is set to 0 templates are recompiled all the time

Have you tried something like this?

from jinja2 import Environment
env = Environment(cache_size=0)
糖果控 2024-12-29 16:21:22

使用 Bottle view 装饰器,您只需执行 @view('your_view', cache_size=0) 即可。

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

如果你想在所有视图中执行此操作,也许你可以这样做:

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

这样,只有在调试模式下才可以执行此操作,在此代码中添加 if 语句 if Bottle.DEBUG

Using bottle view decorator, you can just do @view('your_view', cache_size=0).

Bottle has a reloader=True parameter in server adapter, but I guess it works only with SimpleTemplate. I will try to extend this behaviour to other template engines.

If you want to do it in all your views, maybe you can do something like this:

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

This way, you can do it only when you are in debug mode adding an if statement to this code if bottle.DEBUG.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文