Using Python’s Jinja, I’m concerned with both code readability and correct output. Here is my Jinja template:
M3U_TEMPLATE = jinja2.Template(
textwrap.dedent("""\
#EXTM3U
{% for item in playlist %}
#EXTALB:{{ item.strAlbum }} ({{ item.release }})
#EXTART:{{ item.strAlbumArtists }}
#EXTINF:{{ item.iDuration }},{{ item.strArtists }} - {{ item.strTitle }}
{{ item.path }}
{% endfor %}
""")
)
Python’s textwrap.dedent()
takes care of removing most of indent from the text. But I want to remove also the indents from the block of text inside the {% for %}
loop. I want this kind of result:
#EXTM3U
#EXTALB:Offramp (1982)
#EXTART:Pat Metheny Group
#EXTINF:408,Pat Metheny Group - James
/media/Jazz, Fusion etc/Pat Metheny Group/1982 • Offramp/06 James.m4a
#EXTALB:Blue Moon (1961)
#EXTART:The Marcels
#EXTINF:133,The Marcels - Blue Moon
/media/Pop/The Marcels/1961 • Blue Moon/01 Blue Moon.m4a
But I’m getting this:
#EXTM3U
#EXTALB:Offramp (1982)
#EXTART:Pat Metheny Group
#EXTINF:408,Pat Metheny Group - James
/media/Jazz, Fusion etc/Pat Metheny Group/1982 • Offramp/06 James.m4a
#EXTALB:Blue Moon (1961)
#EXTART:The Marcels
#EXTINF:133,The Marcels - Blue Moon
/media/Pop/The Marcels/1961 • Blue Moon/01 Blue Moon.m4a
I want the item’s block indentation in code, but not in final result. So how to get rid of this? Can’t find a Jinja example that covers my case.
Using Python’s Jinja, I’m concerned with both code readability and correct output. Here is my Jinja template:
M3U_TEMPLATE = jinja2.Template(
textwrap.dedent("""\
#EXTM3U
{% for item in playlist %}
#EXTALB:{{ item.strAlbum }} ({{ item.release }})
#EXTART:{{ item.strAlbumArtists }}
#EXTINF:{{ item.iDuration }},{{ item.strArtists }} - {{ item.strTitle }}
{{ item.path }}
{% endfor %}
""")
)
Python’s textwrap.dedent()
takes care of removing most of indent from the text. But I want to remove also the indents from the block of text inside the {% for %}
loop. I want this kind of result:
#EXTM3U
#EXTALB:Offramp (1982)
#EXTART:Pat Metheny Group
#EXTINF:408,Pat Metheny Group - James
/media/Jazz, Fusion etc/Pat Metheny Group/1982 • Offramp/06 James.m4a
#EXTALB:Blue Moon (1961)
#EXTART:The Marcels
#EXTINF:133,The Marcels - Blue Moon
/media/Pop/The Marcels/1961 • Blue Moon/01 Blue Moon.m4a
But I’m getting this:
#EXTM3U
#EXTALB:Offramp (1982)
#EXTART:Pat Metheny Group
#EXTINF:408,Pat Metheny Group - James
/media/Jazz, Fusion etc/Pat Metheny Group/1982 • Offramp/06 James.m4a
#EXTALB:Blue Moon (1961)
#EXTART:The Marcels
#EXTINF:133,The Marcels - Blue Moon
/media/Pop/The Marcels/1961 • Blue Moon/01 Blue Moon.m4a
I want the item’s block indentation in code, but not in final result. So how to get rid of this? Can’t find a Jinja example that covers my case.
Share Improve this question edited Feb 11 at 1:07 avibrazil asked Feb 9 at 11:35 avibrazilavibrazil 3302 silver badges12 bronze badges 7 | Show 2 more comments4 Answers
Reset to default 0You can just dedent post-rendering. The thing is also - you don't want to dedent template, because template should remain readable - that's why indents on loops, assignment clauses etc. Also - one of the variables coming from rendering might include any spacing character that will break your assumptions.
M3U_TEMPLATE = jinja2.Template(
"""
{% for item in playlist %}
#EXTALB:{{ item.strAlbum }} ({{ item.release }})
#EXTART:{{ item.strAlbumArtists }}
#EXTINF:{{ item.iDuration }},{{ item.strArtists }} - {{ item.strTitle }}
{{ item.path }}
{% endfor %}
"""
)
print(
textwrap.dedent(
M3U_TEMPLATE.render(
playlist=[
{"strAlbum": "album", "release": "v1.0", "strAlbumArtists": "artist", "iDuration": "tooLong", "strArtists": "AnotherArtist", "strTitle": "title", "path": "path"},
{"strAlbum": "album1", "release": "v2.0", "strAlbumArtists": "artist1", "iDuration": "tooLong1", "strArtists": "AnotherArtist1", "strTitle": "title1", "path": "path1"}
]
)
)
)
You can just preprocess the template to remove leading spaces from each line.
template = textwrap.dedent("""\
#EXTM3U
{% for item in playlist %}
#EXTALB:{{ item.strAlbum }} ({{ item.release }})
#EXTART:{{ item.strAlbumArtists }}
#EXTINF:{{ item.iDuration }},{{ item.strArtists }} - {{ item.strTitle }}
{{ item.path }}
{% endfor %}
""")
template_no_leading_spaces = "\n".join(line.lstrip() for line in template.splitlines())
M3U_TEMPLATE = jinja2.Template(template_no_leading_spaces)
Fortunately, Jinja already supports this quite handily in several different ways:
By adding a trailing
-
to the directive - "You can also strip whitespace in templates by hand. If you add a minus sign (-) to the start or end of a block (e.g. a For tag), a comment, or a variable expression, the whitespaces before or after that block will be removed"{% for item in playlist -%}
In your case, since you have multiple lines within the block that are prefixed with "raw" characters, this option will not work (subsequent lines in the loop will still have the wrong indentation).
Use the keyword arguments to
jinja2.Template
that control this behavior for the entire template /Environment
, namelytrim_blocks
andlstrip_blocks
:M3U_TEMPLATE = jinja2.Template( textwrap.dedent(""" {% for item in playlist %} #EXTALB:{{ item.strAlbum }} ({{ item.release }}) #EXTART:{{ item.strAlbumArtists }} #EXTINF:{{ item.iDuration }},{{ item.strArtists }} - {{ item.strTitle }} {{ item.path }} {% endfor %} """), trim_blocks=True, lstrip_blocks=True )
Can you please try this code:
I just introduced an hypen at the end of for loop item object.
M3U_TEMPLATE = jinja2.Template(
textwrap.dedent("""\
#EXTM3U
{% for item in playlist -%}
#EXTALB:{{ item.strAlbum }} ({{ item.release }})
#EXTART:{{ item.strAlbumArtists }}
#EXTINF:{{ item.iDuration }},{{ item.strArtists }} - {{ item.strTitle }}
{{ item.path }}
{% endfor %}
""")
)
playlist
– roganjosh Commented Feb 9 at 12:13\r
. But it wouldn't work for a file opened in a web browser most likely, even if it might to the job in some text editors. – FLAK-ZOSO Commented Feb 9 at 14:04