使用内联和非内联块时的 Jinja2 缩进

Jinja2 indentation when using inline and non-inline blocks

我有以下模板:

{% macro entry(e) %}
<li>
    <a href="{% if 'link' in e %}{{ e.link }}{% else %}{{ e.path }}{% endif %}">
        <code>{{ e.title }}</code>
    </a>{% if e.desc  %} - {{ e.desc }}{% endif %}
    {% if e.date %}<time datetime="{{ e.date }}"> ({{ e.date.split('-')[0] }})</time>{% endif %}
</li>
{% endmacro %}
<ul>
    {% for e in entries %}
    {{ entry(e) }}
    {% endfor %}
</ul>

我正在尝试使用适当的缩进且没有空行将其渲染到此 HTML 中:

<ul>
    <li>
        <a href="link">
            <code>title</code>
        </a> - desc
        <time datetime="2020"> (2020)</time>
    </li>
</ul>

我尝试了 trim_blockslstrip_blocks 的各种排列,但都无济于事。我怎样才能达到预期的输出?

示例代码:

from jinja2 import Environment, FileSystemLoader, Template

foo = (
    (True, True),
    (True, False),
    (False, True),
    (False, False),
)

template_string = """
{% macro entry(e) %}
<li>
    <a href="{% if 'link' in e %}{{ e.link }}{% endif %}">
        <code>{{ e.title }}</code>
    </a>{% if e.desc  %} - {{ e.desc }}{% endif %}
    {% if e.date %}<time datetime="{{ e.date }}"> ({{ e.date.split('-')[0] }})</time>{% endif %}
</li>
{% endmacro %}
<ul>
    {% for e in entries %}
    {{ entry(e) }}
    {% endfor %}
</ul>
"""

entries = [
    {'title': 'title', 'date': '2020', 'desc': 'desc', 'link': 'link'}
]

for trim_blocks, lstrip_blocks in foo:
    env = Environment(trim_blocks=trim_blocks, lstrip_blocks=lstrip_blocks)

    template = env.from_string(template_string)

    print("------------------------")
    print("trim_blocks:", trim_blocks)
    print("lstrip_blocks:", lstrip_blocks)
    print("------------------------")
    print(template.render(entries=entries))

# ------------------------
# trim_blocks: True
# lstrip_blocks: True
# ------------------------
# 
# <ul>
#     <li>
#     <a href="link">
#         <code>title</code>
#     </a> - desc<time datetime="2020"> (2020)</time></li>
# 
# </ul>
# ------------------------
# trim_blocks: True
# lstrip_blocks: False
# ------------------------
# 
# <ul>
#         <li>
#     <a href="link">
#         <code>title</code>
#     </a> - desc    <time datetime="2020"> (2020)</time></li>
# 
#     </ul>
# ------------------------
# trim_blocks: False
# lstrip_blocks: True
# ------------------------
# 
# 
# <ul>
# 
#     
# <li>
#     <a href="link">
#         <code>title</code>
#     </a> - desc
# <time datetime="2020"> (2020)</time>
# </li>
# 
# 
# </ul>
# ------------------------
# trim_blocks: False
# lstrip_blocks: False
# ------------------------
# 
# 
# <ul>
#     
#     
# <li>
#     <a href="link">
#         <code>title</code>
#     </a> - desc
#     <time datetime="2020"> (2020)</time>
# </li>
# 
#     
# </ul>

您需要 trim_blockslstrip_blocks 的组合都是 False。所以,您拥有的最后一个版本实际上非常接近。

要获得所需的输出,您需要使用 Jinja2 提供的 whitespace control 机制。特别是,你会对这个感兴趣:

You can also strip whitespace in templates by hand. If you add a minus sign (-) to the start or end of a block (e.g. a For tag), a comment, or a variable expression, the whitespaces before or after that block will be removed:

因此,通过在 for 循环和 macro 中添加 - 符号,您可以删除扩展时出现的不需要的换行符。

for循环的情况下,将其添加到块的开始和结束的两侧。但是,在 macro 的情况下,只将它添加到一侧——如果将它添加到两侧,它会将 <ul><li> 合并到同一行(并且类似地用于结束标记)。

以下应该适合您:

from jinja2 import Environment, FileSystemLoader, Template

template_string = """
{%- macro entry(e) %}
    <li>
        <a href="{% if 'link' in e %}{{ e.link }}{% endif %}">
            <code>{{ e.title }}</code>
        </a>{% if e.desc  %} - {{ e.desc }}{% endif %}
        {% if e.date %}<time datetime="{{ e.date }}"> ({{ e.date.split('-')[0] }})</time>{% endif %}
    </li>
{% endmacro -%}
<ul>
    {%- for e in entries -%}
        {{ entry(e) }}
    {%- endfor -%}
</ul>
"""

entries = [
    {'title': 'title', 'date': '2020', 'desc': 'desc', 'link': 'link'}
]

env = Environment(trim_blocks=False, lstrip_blocks=False)
template = env.from_string(template_string)
print(template.render(entries=entries))

给出所需的输出:

<ul>
    <li>
        <a href="link">
            <code>title</code>
        </a> - desc
        <time datetime="2020"> (2020)</time>
    </li>
</ul>