jinja2 how to remove trailing newline
Question:
I’m using jinja 2 to output a yaml file but can’t seem to get rid of a trailing newline and the end of a for loop. Eg the below
- request:
path: {{ path }}
headers:
origin: 'somedomain.com'
user-agent: 'agent'
referer: 'some.domain.com'
authority: 'somedomain.com'
querystring:
{% for key, value in querystring.items() -%}
{{ key }}: '{{ value }}'
{% endfor %}
response:
content:
file: {{ content }}
gives me the output:
- request:
path: /some/path
headers:
origin: 'somedomain.com'
user-agent: 'agent'
referer: 'somedomain.com'
authority: 'somedomain.com'
querystring:
postcode: 'xxxxxx'
houseNo: '55'
response:
content:
file: address.json
With an additional unwanted blank line after houseNo. How do I get rid of this line?
Answers:
I think you can get rid of it using the whitespace control feature. Thus I would modify the endfor
block to {% endfor -%}
See if that does it!
Change your loop to strip whitespace from the top AND bottom of the output (notice extra -
at the for
loop close):
{% for key, value in querystring.items() -%}
{{ key }}: '{{ value }}'
{%- endfor %}
In my tests (using https://github.com/abourguignon/jinja2-live-parser), the -
must come after the first {%
, not before the last to achieve what you’re asking for.
Docs: https://jinja.palletsprojects.com/en/latest/templates/#whitespace-control
I found a way to solve this problem:
- request:
path: {{ path }}
headers:
origin: 'somedomain.com'
user-agent: 'agent'
referer: 'some.domain.com'
authority: 'somedomain.com'
querystring: >-
{% for key, value in querystring.items() -%}
{{ key }}: '{{ value }}'
{% endfor %}
response:
content:
file: {{ content }}
>
, |
: “clip”: keep the line feed, remove the trailing blank lines.
>-
, |=
: “strip”: remove the line feed, remove the trailing blank lines.
>+
, |+
: “keep”: keep the line feed, keep trailing blank lines.
Thx Steve Bennett‘s post:
In YAML, how do I break a string over multiple lines?
You can suppress rendering of the below lines:
<% for ... %>
<% endfor %>
<% if ... %>
<% endif %>
by setting trim_blocks=True and lstrip_blocks=True in your jinja2 environment. See the example below, info from their docs
context = {'querystring': querystring, 'path': path, 'content': content}
jinja_env = jinja2.Environment(
loader=jinja2.FileSystemLoader('templates/'),
trim_blocks=True,
lstrip_blocks=True
)
print(jinja_env.get_template('my_template.yaml').render(context))
For those using Flask who arrive here, these lines did the trick for me:
app = Flask(__name__)
app.jinja_env.lstrip_blocks = True
app.jinja_env.trim_blocks = True
The accepted answer is only half of the solution, because it removes all newlines.
You can avoid the trailing newline by first removing all newlines (using the minus signs at -%}
and {%-
in the for loop), and then inserting the desired newlines at the right place (using the loop.last
condition).
The following templates renders a dictionary, d, to as JSON text:
{
{% for key, value in d.items() -%}
"{{ key }}": "{{ value }}"{{ ",
" if not loop.last }}
{%- endfor %}
}
For d = {'a':'1', 'b':'2'}
, the template renders to
{
"a": "1",
"b": "2"
}
I’m using jinja 2 to output a yaml file but can’t seem to get rid of a trailing newline and the end of a for loop. Eg the below
- request:
path: {{ path }}
headers:
origin: 'somedomain.com'
user-agent: 'agent'
referer: 'some.domain.com'
authority: 'somedomain.com'
querystring:
{% for key, value in querystring.items() -%}
{{ key }}: '{{ value }}'
{% endfor %}
response:
content:
file: {{ content }}
gives me the output:
- request:
path: /some/path
headers:
origin: 'somedomain.com'
user-agent: 'agent'
referer: 'somedomain.com'
authority: 'somedomain.com'
querystring:
postcode: 'xxxxxx'
houseNo: '55'
response:
content:
file: address.json
With an additional unwanted blank line after houseNo. How do I get rid of this line?
I think you can get rid of it using the whitespace control feature. Thus I would modify the endfor
block to {% endfor -%}
See if that does it!
Change your loop to strip whitespace from the top AND bottom of the output (notice extra -
at the for
loop close):
{% for key, value in querystring.items() -%}
{{ key }}: '{{ value }}'
{%- endfor %}
In my tests (using https://github.com/abourguignon/jinja2-live-parser), the -
must come after the first {%
, not before the last to achieve what you’re asking for.
Docs: https://jinja.palletsprojects.com/en/latest/templates/#whitespace-control
I found a way to solve this problem:
- request:
path: {{ path }}
headers:
origin: 'somedomain.com'
user-agent: 'agent'
referer: 'some.domain.com'
authority: 'somedomain.com'
querystring: >-
{% for key, value in querystring.items() -%}
{{ key }}: '{{ value }}'
{% endfor %}
response:
content:
file: {{ content }}
>
,|
: “clip”: keep the line feed, remove the trailing blank lines.>-
,|=
: “strip”: remove the line feed, remove the trailing blank lines.>+
,|+
: “keep”: keep the line feed, keep trailing blank lines.
Thx Steve Bennett‘s post:
In YAML, how do I break a string over multiple lines?
You can suppress rendering of the below lines:
<% for ... %>
<% endfor %>
<% if ... %>
<% endif %>
by setting trim_blocks=True and lstrip_blocks=True in your jinja2 environment. See the example below, info from their docs
context = {'querystring': querystring, 'path': path, 'content': content}
jinja_env = jinja2.Environment(
loader=jinja2.FileSystemLoader('templates/'),
trim_blocks=True,
lstrip_blocks=True
)
print(jinja_env.get_template('my_template.yaml').render(context))
For those using Flask who arrive here, these lines did the trick for me:
app = Flask(__name__)
app.jinja_env.lstrip_blocks = True
app.jinja_env.trim_blocks = True
The accepted answer is only half of the solution, because it removes all newlines.
You can avoid the trailing newline by first removing all newlines (using the minus signs at -%}
and {%-
in the for loop), and then inserting the desired newlines at the right place (using the loop.last
condition).
The following templates renders a dictionary, d, to as JSON text:
{
{% for key, value in d.items() -%}
"{{ key }}": "{{ value }}"{{ ",
" if not loop.last }}
{%- endfor %}
}
For d = {'a':'1', 'b':'2'}
, the template renders to
{
"a": "1",
"b": "2"
}