在jinja模板中如何合理定义默认变量值?

13 投票
3 回答
15445 浏览
提问于 2025-04-16 08:43

我想在我的Jinja模板中设置一些变量的默认值,而且希望能在模板内部直接设置。看了Jinja2的文档,我没有找到这样的办法。难道我漏掉了什么吗?我看到有“default”这个过滤器,但我想要的是在整个模板中设置默认值,而不是每次使用时都设置。

我花了大约一个小时试图自学Jinja2扩展的写法,想写一个叫setdefault的扩展标签,可能长得像这样:

{% setdefault animal = 'wumpas' %}

我希望的效果是,如果被赋值的名字是未定义的,就像set标签那样工作,但如果这个名字已经定义了,就不产生任何效果。不过到目前为止,我还没能让这个工作。

我的解决办法是完全绕过Jinja,做一个复合文件;在一个特殊标记之前的部分是默认值的(yaml)映射,而标记之后的部分是Jinja模板。一个看起来能正常工作的概念验证实现是:

skel_text = """\
animal: wumpas
%%
The car carried my {{animal}} to the vet.
"""
class Error(Exception): pass
_skel_rx = re.compile(
    r"""((?P<defaults>.*?)^%%[ \t]*\n)?(?P<template>.*)""",
    re.MULTILINE|re.DOTALL)
_env = jinja2.Environment(trim_blocks=True)
def render(skel, **context):
    m = _skel_rx.match(skel_text)
    if not m:
        raise Error('skel split failed')
    defaults = yaml.load(m.group('defaults') or '{}')
    template = _env.from_string(m.group('template') or '')
    template.globals.update(defaults)
    return template.render(**context)

print render(skel_text)
print render(skel_text, animal='cat')

那么,在标准的Jinja2中,有没有办法做到类似的效果,或者怎么写一个扩展来实现我想要的效果呢?

3 个回答

1

更新一下,Jinja2有一种方法可以为变量设置默认值,如果这些变量“失败”的话。这里的“失败”是指它们没有值。

{{ variable | default(0) }}

这段代码会把一个变量的值设置为0,如果在模板中没有提供这个变量的值。如果你的变量是一个字典,那么可以使用下面这段代码:

{{ dict['key'] | default(0) }}

在这种情况下,如果字典中的'key'的值没有定义,或者根本就不存在这个'key',那么它的值会被设置为0。

想了解更多信息,可以查看:Jinja2过滤器文档

32

对我有效的方法是使用一个过滤器:

t = '''Hello {{name | default('John Doe')}}'''
14

这个set 控制结构可以实现你想要的功能。

下面是我用来测试的一些代码:

from jinja2 import Template
t = '''{% set name=name or "John Doe" %}Hello {{ name }}'''
template = Template(t)
print template.render(name='Jonnie Doe')
print template.render()

结果如预期,输出是:

Hello Jonnie Doe
Hello John Doe

撰写回答