Jinja2: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
(One intermediate revision by the same user not shown)
Line 97: Line 97:
{%- endif %}
{%- endif %}
</syntaxhighlight>
</syntaxhighlight>
<font color=darkkhaki>
The following construct broke the renderer when <code>some_var</code> was <code>None</code>:
<syntaxhighlight lang='jinja'>
{%if some_var is some_var and not none(some_var) -%}
{{ queues }}
{%- endif %}
</syntaxhighlight>
Error message:
>  ???
E  TypeError: 'NoneType' object is not callable
</font>


==Specific Boolean Values==
==Specific Boolean Values==

Revision as of 21:04, 6 June 2023

External

Internal

TODO

What happens if a document containing a variable is rendered and the variable value is not provided?

Overview

Playground

https://github.com/ovidiuf/playground/tree/master/pyhton/jinja2

Programming Model

Find out what the latest version is from https://pypi.org/project/Jinja2/

Then add this to your requirements.txt

jinja2 == 3.0.3

Once the virtual environment is updated, use it as such:

from pathlib import Path
from jinja2 import Environment, FileSystemLoader

template_dir = Path('...')
text = Environment(loader=FileSystemLoader(template_dir))\
  .get_template('my-template.yaml.j2') \
  .render(variable_1='some value', variable_2='some other value')

If the content is already loaded:

template_as_text = '...'
rtemplate = Environment().from_string(template_as_text)
data = rtemplate.render(variable_1='some value', variable_2='some other value')

Variables

Variables can be provided individually as arguments of the render() method.

Alternatively, a recursive data structure can be provided as argument.

Templating Language

Variable

raw content followed by {{ variable1 }}

Conditional

{%if some_var == "something" -%}
something
something else {{ var_1 }}
{% elif some_var == "something else" -%}
something else
{% else %}
something completely different {{ var_2 }}
{%- endif %}

This works with empty strings too:

{%if some_var != "" -%}
my var is {{ some_var }}

defined Conditional

To check whether a variable is defined or not defined:

{%if some_var is defined  -%}
something
{%- endif %}
{%if some_var is not defined  -%}
something else
{%- endif %}

Check whether a Value is None

Note that a variable that has a None value is still defined, so the above is defined test will pass.

To check for None, specifically:

{%if none(some_var)  -%}
'som_var' is None
{%- endif %}

The following construct broke the renderer when some_var was None:

{%if some_var is some_var and not none(some_var) -%}
{{ queues }}
{%- endif %}

Error message:

>   ??? 
E   TypeError: 'NoneType' object is not callable

Specific Boolean Values

To check for a specific boolean value:

{%if some_var == false  -%}
something
{%- endif %}

Type Conditional

To check whether a value is a string:

{%if some_var is string  -%}
something
{%- endif %}

For more built-in filters and tests:

https://www.webforefront.com/django/usebuiltinjinjafilters.html

Conditional Expressions

{%if some_var == "a" and some_other_var == "b" -%}
my vars are {{ some_var }}, {{ some_other_var }}

Loops

my_list:
  {%- for i in seq %}
  - '{{ i }}'
  {%- endfor %}

where seq is a Python list:

seq = ['a', 'b']
text = Environment(loader=FileSystemLoader(template_dir)).get_template('my-template.yaml.j2').render(seq=seq)

Rendering Dictionaries

from jinja2 import Environment

template_as_text = '''
something:
{%- for key, value in a_dict.items() %}
    {{key}}: {{value-}} 
{% endfor %}
somethingelse
'''
a_dict = {'a': 'A', 'b': 'B', 'c': 'C'}
rtemplate = Environment().from_string(template_as_text)
data = rtemplate.render(a_dict=a_dict)
print(data)

This will render:

something:
    a: A
    b: B
    c: C
somethingelse

Rendering a List of Dictionaries

{% if a_list_of_maps %}
  some_tag_that_introduces_the_list_of_maps:
{% for m in a_list_of_maps %}
    -
{% for k, v in m.items() %}
       {{ k }}: {{ v }}
{% endfor %}
{%- endfor %}
{%- endif %}

Rendering Embedded Maps

If a complex recursive data structure, such as embedded maps, is passed to render(), an arbitrary level key can be accessed with the dot notation and also by key:

m = {
    'm1': {
        'color': 'red'
    },
    'm2': {
        'color': 'blue'
    }
}

template_as_text = '''
color1: {{ m.m1.color }}
color2: {{ m['m2']['color'] }}
'''
rtemplate = Environment().from_string(template_as_text)
data = rtemplate.render(m=m)
print(data)

will print:

color1: red
color2: blue

Rendering an Object's __str__() Representation

The __str__() is honored, but if it is a multi-line string, only the first line is correctly indented.

Whitespace Management

A leading dash removes all whitespace (including new lines) between the last non space template character and it. A trailing dash removes all whitespace (including new lines) between it and the next non-whitespace character from the template.

 {{-
 -}}
 {%-
 -%}

Indentation

  some_tag:
    {{ rendered_multiline_configuration | indent(4) }}

The first line must be explicitly indented with the same number of space. The spaces are added after each new line.

Filters

Filters