How to indent nested if/for statements in jinja2
Asked Answered
C

2

11

I have a long Jinja2 template which has many nested if/for statements. It's very hard to read. I would like to indent the {% %} bits, to make it clearer. However if I do that, the contents of those blocks gets indented further too.

How can I indent just the {% %} bits?

I'm using Ansible.

Steps to reproduce:

template.yaml.j2

{% for x in range(3) %}
Key{{ x }}:
   # The following should be one list
   - always here
   {% if x % 2 %}
   - sometimes here
   {% endif %}
{% endfor %}

playbook.yaml

---
- hosts: localhost
  connection: local

  tasks:
    - template:
        src: template.j2
        dest: template.yaml

Run with ansible-playbook playbook.yaml

Desired Output

Key0:
   # The following should be one list
   - always here
Key1:
   # The following should be one list
   - always here
   - sometimes here
Key2:
   # The following should be one list
   - always here

Actual behavior:

Key0:
   # The following should be one list
   - always here
   Key1:
   # The following should be one list
   - always here
      - sometimes here
   Key2:
   # The following should be one list
   - always here

Workaround

If I unindent the if statements like:

{% for x in range(3) %}
Key{{ x }}:
   # The following should be one list
   - always here
{% if x % 2 %}
   - sometimes here
{% endif %}
{% endfor %}

Then I get the output I want. But the problem is that this is hard to read. (In my actual template, I have if statements inside for inside if, etc. Highly nested.)

Concentric answered 10/9, 2019 at 6:0 Comment(0)
C
16

Q: "How to indent nested if/for statements in Jinja2?"

A: Turn off default trimming and manually ltrim only indented control statements {%-. For example, the template below does what you're looking for

shell> cat templates/template.j2
#jinja2: trim_blocks: False
{% for x in range(3) %}
Key{{ x }}:
   # The following should be one list
   - always here
   {%- if x % 2 %}
   - sometimes here
   {%- endif %}
{%- endfor %}

The task

    - template:
        src: template.j2
        dest: template.yaml

creates the file template.yaml

shell> cat template.yaml 

Key0:
  # The following should be one list
  - always here
Key1:
  # The following should be one list
  - always here
  - sometimes here
Key2:
  # The following should be one list
  - always here

See Whitespace Control.


Notes

  1. The dash in {%- endfor %} removes the empty line among the keys.

  2. By default parameter trim_blocks: yes. See template.

  3. The documentation section Whitespace Control says:

You can manually disable the trim_blocks behavior by putting a plus sign (+) at the end of a block

Then, the following template gives the same result

shell> cat templates/template.j2
{% for x in range(3) %}
Key{{ x }}:
  # The following should be one list
  - always here
  {%- if x % 2 +%}
  - sometimes here
  {%- endif +%}
{% endfor %}
Clupeid answered 10/9, 2019 at 6:56 Comment(0)
F
0

I had to fight with the manual whitespace control. I ended up adding whitespace in the template tags, like this:

{% for x in range(3) %}
Key{{ x }}:
   # The following should be one list
   - always here
{%   if x % 2 %}
   - sometimes here
{%   endif %}
{% endfor %}

Note the extra space before the if and endif.

Fara answered 29/2 at 16:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.