Jinja docx 模板,避免嵌套换行

Jinja docx template, avoiding new line in nested for

我想知道是否有办法避免在带有 jinja 的 docx 模板中的 for 内使用换行符。代码如下:

{% for customer in customers %}
{% for account in customer.accounts %}
{{ account.number }}
{% endfor %}{% endfor %}. 

但结果是用行分隔的帐号:

234090

29292

29292

我正在 LibreOffice 上进行测试。

有人可以帮我吗?

了解额外的换行符(以及行)来自哪里

Jinja 模板中的空格不会被忽略。所以Jinja看到的是

{% for customer in customers %}¶
{% for account in customer.accounts %}¶
{{ account.number }}¶
{% endfor %}{% endfor %}.·¶

而且它实际上并不太在意行数,所以制作那个

{% for customer in customers %}¶{% for account in customer.accounts %}¶{{ account.number }}¶{% endfor %}{% endfor %}.·¶

这就是循环

{% for customer in customers %}…{% endfor %}.·

和body

¶{% for account in customer.accounts %}¶{{ account.number }}¶{% endfor %}

注意开头的外层循环的其余部分body是另一个循环

{% for account in customer.accounts %}…{% endfor %}

和body

¶{{ account.number }}¶

注意开头和结尾的

因此,您将在每个单独客户的组帐户之前得到一个换行符,并且在每个帐号前后各有一个换行符。您可能不想摆脱所有这些,因为那样会将所有数字粘在一起在一行上而没有任何分隔:

2340902929229292

缓解

除了你想要的那些之外,你可以避免换行符:

{% for customer in customers %}{% for account in customer.accounts %}{{ account.number }}¶
{% endfor %}{% endfor %}.·¶

不过,这会使模板难以阅读。您可以让 Jinja2 忽略模板标签之间的空格。为此,请在相关空白之前的标记末尾或该空白之后的标记开头(或两者)添加 -

{% for customer in customers -%}
{% for account in customer.accounts -%}
{{ account.number }}
{% endfor -%}
{% endfor %}. 

{% for customer in customers %}
{%- for account in customer.accounts %}
{{- account.number }}
{%- endfor %}
{% endfor %}. 

{% for customer in customers -%}
{%- for account in customer.accounts -%}
{{- account.number }}
{% endfor -%}
{%- endfor %}. 

(见Jinja2 documentation

这甚至允许您使用缩进,而不会在结果中出现额外的空格:

{% for customer in customers -%}
  {% for account in customer.accounts -%}
    {{ account.number }}{{ '\n' -}}
  {% endfor -%}
{% endfor %}. 

{% for customer in customers %}
  {%- for account in customer.accounts %}
    {{- account.number }}{{ '\n' }}
  {%- endfor %}
{% endfor %}. 

{% for customer in customers -%}
  {%- for account in customer.accounts -%}
    {{- account.number }}{{ '\n' -}}
  {% endfor -%}
{%- endfor %}. 

我使用了这样一个事实,即不仅变量而且文字都可以用在模板标签中,所以我可以用 {{ '\n' }} 产生一个换行符。对于这种样式,这是必要的,因为 - 吃掉缩进也会吞下模板源中的(字面量)换行符。

您可以抑制以下行的呈现:

<% for ... %>
<% endfor %>
<% if ... %>
<% endif %>

通过在您的 jinja2 环境中设置 trim_blocks=True 和 lstrip_blocks=True。请参阅下面的示例,信息来自 their docs

context = {'querystring': querystring, 'path': path, 'content': content}    
loader = jinja2.FileSystemLoader('templates/')
jinja_env = jinja2.Environment(loader=loader, trim_blocks=True, lstrip_blocks=True)
print(jinja_env.get_template('my_template.yaml').render(context))

受 das-g 答案的启发,我遇到了类似的问题,经过大量的反复试验后我放弃了并决定始终删除换行符但像他一样手动添加换行符,但前提是不是最后循环索引,所以我的宏最终是这样的:

{% macro service_envs() %}
{% if app_envs is defined %}
    environment:
{% for env in app_envs %}
      - {{ env }}{% if not loop.last %}{{ '\n' }}{% endif %}
{%- endfor %}
{% endif %}
{% endmacro %}

结果是:

    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    ports:
      - 5432:5432

重要的部分是删除 {%- endfor %} 中的空格,但将其添加到 if 语句中。 所以在我的例子中,空格被保留了下来,但我没有为列表的最后一项换行。所以我的下一行就在我的环境列表之后。现在我不需要在每次调用宏时都添加 {{- }} 。 使用 ansible 版本 2.5.0

进行测试

感谢@das-g 的详细评论。他解释了 space 是如何来的,但没有说明 Jinja 是如何吃掉白色 space 的。我想在这里为我和其他有同样问题的人添加一些评论。

{%- for customer in customers %}: 移除 for-loop 块前的白色 space

{% for customer in customers -%}: 删除每个 for-loop 项目前的白色 space

{%- endfor %}: 删除每个 for-loop 项后的白色 space

{% endfor -%}: 在 for 循环块

之后删除白色 space

简单来说,

{% for %} 这个标签后面有一个换行符,即{% for %}¶

{% for -%} 先去掉标签后的换行符再展开循环

endfor 标签的想法相同

如果不需要换行,那么我们可以将语句放在单行中,如下所示 <% for … %><% if … %><% endif %><% endfor %>.

用这个Jinj2,解析不会引入新行