如何将自定义过滤器嵌入jinja2模板?

23 投票
2 回答
39268 浏览
提问于 2025-04-18 18:12

我正在写一些Jinja2模板,希望能在相关项目中尽量方便地重复使用。 我有一套自定义的便利过滤器,希望这些模板能“携带”它们。 有没有什么Jinja2的语法可以把过滤器的定义直接放到模板里? 或者有没有什么方法可以把纯Python函数嵌入到Jinja2模板中,这样它就能对传入模板的变量进行操作? 我以前用过mako,在那里做这个非常简单,但在mako中处理LaTeX模板很麻烦,因为缺少自定义语法,所以我不得不换用Jinja2。

2 个回答

20

jinja2模板中,有一种简单的方法可以添加自定义过滤器。FILTERS是一个字典,里面包含了我们可以用来渲染模板的所有过滤器。不过,我们还可以往里面添加更多的过滤器。

下面是一个快速的例子,教你如何添加新的过滤器。


from jinja2 import Template
from jinja2.filters import FILTERS, environmentfilter


// Remove the decorator in the next line if using version 3.1.0 or higher, read below
@environmentfilter
def do_reverse_by_word(environment, value, attribute=None):
    """
    custom max calculation logic
    """
    if attribute:
        return [list(reversed(i.get(attribute).split())) for i in value]

    return list(reversed(value.split()))


FILTERS["reverse_by_word"] = do_reverse_by_word
print(Template("{{ name | reverse_by_word }}").render({"name": "Stack Overflow"}))
print(Template("{{ names | reverse_by_word(attribute='name') }}").render({"names": [{"name": "Stack Overflow"}, {"name": "Stack Exchange"}]}))


输出结果

['Overflow', 'Stack']
[['Overflow', 'Stack'], ['Exchange', 'Stack']]

如果你有更复杂的使用场景,请在下面留言。我会很高兴回答你的所有问题。

更新(经过3.1.2版本测试):现在不再需要使用environmentfilter这个装饰器(而且它已经不存在了)。来源

41

你不能直接把Python代码嵌入到Jinja2模板里。根据我所知道的,正确的方法是在你的应用程序中定义这些代码,然后把它们添加到你的Jinja2环境实例中。下面是一个例子,来自于https://jinja.palletsprojects.com/en/2.11.x/api/#writing-filters

import jinja2

loader = jinja2.FileSystemLoader('/tmp')
env = jinja2.Environment(autoescape=True, loader=loader)

def upperstring(input):
    """Custom filter"""
    return input.upper()

env.filters['upperstring'] = upperstring
temp = env.get_template('template.html')
temp.render(name="testing")

这是我使用的模板

{{ name | upperstring }}

结果是这样的

TESTING

撰写回答