简体   繁体   中英

Jinja2 indentation when using inline and non-inline blocks

I have the template below:

{% 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>

which I'm trying to render into this HTML with proper indentation and no blank lines:

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

I've tried various permutations of trim_blocks and lstrip_blocks to no avail. How can I achieve the desired output?

Sample code:

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>

You will want the combination of trim_blocks and lstrip_blocks both being False . So, the last version you have is actually quite close.

To achieve the desired output though, you will need to make use of whitespace control mechanisms provided by Jinja2. In particular, you will be interested in this:

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

Therefore, by adding - signs in the for loop and macro , you can remove the unwanted newlines which occur upon expansion.

In the case of the for loop, add it to both sides of start and end of the block. However, in the case of the macro , add it only on one side -- if you add it to both, it will merge the <ul> and <li> onto the same line (and similarly for the closing tags).

The following should work for you:

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

Which gives the desired output:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM