Partially render in Jinja
A Jinja template can be rendered. Sometimes the data we need can not be collected in just one place. It will be helpful if we can render a template multiple times.
By default, a Jinja template can not be rendered multiple times. It will raise an exception or insert null values into the corresponding placeholders.
In the blog, we will use a trick to mimic the partially rendering behavior. Jinja has an operator raw which can be used to render its original content.
1
2
3
4
5
6
7
8
9
10
11
12
13
from jinja2 import Template
template_str = """
{% raw %}
{{hi}}
{% endraw %}
"""
partial_template_str = Template(template_str).render()
result = Template(partial_template_str).render(hi=3)
But using raw will introduce redundant newlines. We can not use - to remove the spaces. It is wrong sometimes we remove the leading spaces.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from jinja2 import Template
template_str = """
{% raw %}
{{hi}}
{% endraw %}
"""
partial_template_str = Template(template_str, trim_blocks=True, lstrip_blocks=True).render()
result = Template(partial_template_str).render(hi=3)
print(result)
If the leading spaces are not meaningless to your program, you can use - to remove them. Referecne
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from jinja2 import Template
template_str = """
{% raw -%}
{{hi}}
{% endraw %}
"""
partial_template_str = Template(template_str, trim_blocks=True, lstrip_blocks=True).render()
result = Template(partial_template_str).render(hi=3)
print(result)
If we need more nested templates, such as we want a template to be rendered three or more times, the code will be ugly. It seems that Jinja does not provide way to implement a customized operator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from jinja2 import Template
template_str = """
{% raw -%}
{{hi}}
{% endraw -%}
{{'{%'}} raw {{'%}'}}
{{hello}}
{{'{%'}} endraw {{'%}'}}
"""
partial_template_str = Template(template_str, trim_blocks=True, lstrip_blocks=True).render()
print(partial_template_str)
print("=" * 10)
result = Template(partial_template_str).render(hi=3)
print(result)
print("=" * 10)
final_result = Template(result).render(hello=4)
print(final_result)
raw and endraw can not be nested. You are not allowed to insert raw and endraw block in another raw and endraw block`.