在瓶中使用 jinja2 中的自定义过滤器
Custom filter in jinja2 using in bottle
我尝试使用 bottle (not flask). Suppose I want to define a pandoc
custom filter. Regarding the jinja2 documentation 在 jinja2 中定义自定义过滤器,我必须这样定义它:
from bottle import jinja2_view as view, jinja2_template as template
from jinja2 import environment, filters
def pandoc_convert(s):
return pypandoc.convert_text(s, format='md', to='html5')
@get("/foo")
def foo():
return template('foo.html')
environment = jinja2.Environment()
# Putting my custom filter.
environment.filters['pandoc'] = pandoc_convert
run(host='localhost', port=8080, debug=True)
在模板中 foo.html
我有
{{ "This is *some* markdown" | pandoc }}
当我 运行 瓶子代码时,它让我:
jinja2.exceptions.TemplateAssertionError: No filter named 'pandoc'
但如果您打印 environment.filters
,则 'pandoc': <function pandoc_convert at 0x7f827e233040>}
会出现在该打印中。
(已更新)
此答案提供了使用 Jinja 的一般说明,但是
看起来好像 bottle
有自己特殊的做事方式。你
需要忽略关于环境和过滤器的 Jinja 文档,
而是深入研究瓶子的来源;具体来说,
Jinja2Template,看起来像这样:
class Jinja2Template(BaseTemplate):
def prepare(self, filters=None, tests=None, globals={}, **kwargs):
from jinja2 import Environment, FunctionLoader
self.env = Environment(loader=FunctionLoader(self.loader), **kwargs)
if filters: self.env.filters.update(filters)
...
请注意,prepare
方法接受一个 filters
关键字参数,用于在其创建的环境中设置过滤器。
jinja2_template
函数,定义如下:
jinja2_template = functools.partial(template, template_adapter=Jinja2Template)
最后,template 函数,其中包括:
if tplid not in TEMPLATES or DEBUG:
settings = kwargs.pop('template_settings', {})
if isinstance(tpl, adapter):
TEMPLATES[tplid] = tpl
if settings: TEMPLATES[tplid].prepare(**settings)
elif "\n" in tpl or "{" in tpl or "%" in tpl or '$' in tpl:
TEMPLATES[tplid] = adapter(source=tpl, lookup=lookup, **settings)
else:
TEMPLATES[tplid] = adapter(name=tpl, lookup=lookup, **settings)
所以,当您调用 jinja2_template("foo.html")
(这就是您
做),这就变成了:
template("foo.html", template_adapter=Jinja2Template)
并且在 template
函数中,模板将调用 prepare
Jinja2Template
的方法,关键字参数来自 settings
,
它来自 template_settings
到 template
的参数。所以,
我们可以使用这样的自定义过滤器:
import bottle
def hellofilter(value):
return value.replace("hello", "goodbye")
@bottle.get("/foo")
def foo():
settings = {
"filters": {
"hello": hellofilter,
}
}
return bottle.jinja2_template("foo.html", template_settings=settings)
if __name__ == "__main__":
bottle.run(host="127.0.0.1", port=7070, debug=True)
如果我的模板 foo.html
如下所示:
This is a test. {{ "hello world"|hello }}
请求 127.0.0.1:7070/foo
将 return:
This is a test. goodbye world
如果我们不想每次都传递 template_settings
参数
我们调用 jinja2_template
,我们可以自己使用 functools.partial
为 jinja2_template
函数创建包装器:
import bottle
import functools
def hellofilter(value):
return value.replace("hello", "goodbye")
template_settings = {
"filters": {
"hello": hellofilter,
},
}
template = functools.partial(
bottle.jinja2_template, template_settings=template_settings
)
@bottle.get("/foo")
def foo():
return template("foo.html")
if __name__ == "__main__":
bottle.run(host="127.0.0.1", port=7070, debug=True)
我尝试使用 bottle (not flask). Suppose I want to define a pandoc
custom filter. Regarding the jinja2 documentation 在 jinja2 中定义自定义过滤器,我必须这样定义它:
from bottle import jinja2_view as view, jinja2_template as template
from jinja2 import environment, filters
def pandoc_convert(s):
return pypandoc.convert_text(s, format='md', to='html5')
@get("/foo")
def foo():
return template('foo.html')
environment = jinja2.Environment()
# Putting my custom filter.
environment.filters['pandoc'] = pandoc_convert
run(host='localhost', port=8080, debug=True)
在模板中 foo.html
我有
{{ "This is *some* markdown" | pandoc }}
当我 运行 瓶子代码时,它让我:
jinja2.exceptions.TemplateAssertionError: No filter named 'pandoc'
但如果您打印 environment.filters
,则 'pandoc': <function pandoc_convert at 0x7f827e233040>}
会出现在该打印中。
(已更新)
此答案提供了使用 Jinja 的一般说明,但是
看起来好像 bottle
有自己特殊的做事方式。你
需要忽略关于环境和过滤器的 Jinja 文档,
而是深入研究瓶子的来源;具体来说,
Jinja2Template,看起来像这样:
class Jinja2Template(BaseTemplate):
def prepare(self, filters=None, tests=None, globals={}, **kwargs):
from jinja2 import Environment, FunctionLoader
self.env = Environment(loader=FunctionLoader(self.loader), **kwargs)
if filters: self.env.filters.update(filters)
...
请注意,prepare
方法接受一个 filters
关键字参数,用于在其创建的环境中设置过滤器。
jinja2_template
函数,定义如下:
jinja2_template = functools.partial(template, template_adapter=Jinja2Template)
最后,template 函数,其中包括:
if tplid not in TEMPLATES or DEBUG:
settings = kwargs.pop('template_settings', {})
if isinstance(tpl, adapter):
TEMPLATES[tplid] = tpl
if settings: TEMPLATES[tplid].prepare(**settings)
elif "\n" in tpl or "{" in tpl or "%" in tpl or '$' in tpl:
TEMPLATES[tplid] = adapter(source=tpl, lookup=lookup, **settings)
else:
TEMPLATES[tplid] = adapter(name=tpl, lookup=lookup, **settings)
所以,当您调用 jinja2_template("foo.html")
(这就是您
做),这就变成了:
template("foo.html", template_adapter=Jinja2Template)
并且在 template
函数中,模板将调用 prepare
Jinja2Template
的方法,关键字参数来自 settings
,
它来自 template_settings
到 template
的参数。所以,
我们可以使用这样的自定义过滤器:
import bottle
def hellofilter(value):
return value.replace("hello", "goodbye")
@bottle.get("/foo")
def foo():
settings = {
"filters": {
"hello": hellofilter,
}
}
return bottle.jinja2_template("foo.html", template_settings=settings)
if __name__ == "__main__":
bottle.run(host="127.0.0.1", port=7070, debug=True)
如果我的模板 foo.html
如下所示:
This is a test. {{ "hello world"|hello }}
请求 127.0.0.1:7070/foo
将 return:
This is a test. goodbye world
如果我们不想每次都传递 template_settings
参数
我们调用 jinja2_template
,我们可以自己使用 functools.partial
为 jinja2_template
函数创建包装器:
import bottle
import functools
def hellofilter(value):
return value.replace("hello", "goodbye")
template_settings = {
"filters": {
"hello": hellofilter,
},
}
template = functools.partial(
bottle.jinja2_template, template_settings=template_settings
)
@bottle.get("/foo")
def foo():
return template("foo.html")
if __name__ == "__main__":
bottle.run(host="127.0.0.1", port=7070, debug=True)