Jinja docx template, avoiding new line in nested for

Patterson Junior picture Patterson Junior · Aug 16, 2017 · Viewed 10.6k times · Source

I was wondering if there is a way to avoid newline characters inside a for in a docx template with jinja. The code is as follows:

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

But the result is account numbers separated by row:

234090

29292

29292

I'm testing on LibreOffice.

Could someone help me?

Answer

das-g picture das-g · Aug 16, 2017

understanding where the extra linebreaks (and thus lines) come from

Whitespace in a Jinja template isn't being ignored. So what Jinja sees is

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

And it actually doesn't care about lines too much, so make that

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

So that is the loop

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

with body

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

Note the at the beginning. The rest of the outer loop's body is another loop

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

with body

¶{{ account.number }}¶

Note the s at the beginning and end.

So you'll get a line break before the group accounts of each separate customer, and another line break before and after each account number. You probably don't want to get rid of all of them, because that would glue all the numbers together on a single line without any separation:

2340902929229292

mitigation

You can just avoid the line breaks except for the ones you want:

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

That makes the template hard to read, though. You can let Jinja2 ignore whitespace between template tags. To do that, add a - at the end of the tag preceding the whitespace in question or at the beginning of the tag following that whitespace (or both):

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

or

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

or

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

(See Jinja2 documentation)

This even allows you to use indentation without having that additional whitespace end up in the result:

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

or

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

or

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

I've used the fact that not just variables but also literals can be used in template tags, so that I can produce a line break with {{ '\n' }}. This is necessary with this style, as a - to eat the indentation would swallow the (literal literal) line break in your template source, too.