I’m trying to use the jinja2 moudle… It’s working differently than I expected.
The value of the variable has_swimming
should change within the for loop, but it resets to the initial value.
The code below is intended to perform a function that finds instances where the hobby is SWIMMING in a list of dictionaries, and wraps them with the desired String characters above and below.
from jinja2 import Environment
if __name__ == '__main__':
template = \
'''
{% set has_swimming = 0 %}
{% for row in Class['Students'] %}
{% set name = row['name'] -%}
{% set hobby = row['hobby'] %}
{% if hobby == 'SWIMMING' and has_swimming == 0 %}
{% set has_swimming = 1 %}
find swim=============
{% endif %}
name is {{name}}, hobby is {{hobby}}
{% if hobby != 'SWIMMING' and has_swimming == 1 %}
{% set has_swimming = 0 %}
end===============
{% endif %}
{% endfor %}
{% if has_swimming == 1%}
end===============
{% endif %}
'''
env = Environment(extensions=['jinja2.ext.i18n', 'jinja2.ext.do', 'jinja2.ext.loopcontrols'],
trim_blocks=True, lstrip_blocks=True)
new_template = env.from_string(template)
test_table = dict()
test_table['Class'] = dict()
test_table['Class']['Students'] = list()
test_table['Class']['Students'].append({'name': 'CHOI', 'hobby': 'RUNNINg'})
test_table['Class']['Students'].append({'name': 'KIM', 'hobby': 'RUNNINg'})
test_table['Class']['Students'].append({'name': 'JEON', 'hobby': 'SWIMMING'})
test_table['Class']['Students'].append({'name': 'YOON', 'hobby': 'SWIMMING'})
write_text = new_template.render(test_table)
print(write_text)
I have a question about the initialization of the has_swimming
variable in the code above.
The code {% set has_swimming = 0 %}
initializes the variable to 0 before entering the for loop.
Then, if the hobby
of the current row is ‘swimming’,
{% if hobby == 'SWIMMING' and has_swimming == 0 %}
{% set has_swimming = 1 %}
Current output result:
name is CHOI, hobby is RUNNINg
name is KIM, hobby is RUNNINg
find swim=============
name is JEON, hobby is SWIMMING
find swim=============
name is YOON, hobby is SWIMMING
Expected output result:
name is CHOI, hobby is RUNNINg
name is KIM, hobby is RUNNINg
find swim=============
name is JEON, hobby is SWIMMING
name is YOON, hobby is SWIMMING
end===============
I can’t understand, the has_swimming
value should be set ‘1’, but on next row, value of has_swimming
resets to zero…
>Solution :
The end===============
is never printed because the assignment {% set has_swimming = 1 %}
is limited to inside the surrounding loop block. Per the documentation for the for
block from the Jinja2 docs:
Please note that assignments in loops will be cleared at the end of the iteration and cannot outlive the loop scope.
This behavior is also further discussed under Assignments:
Please keep in mind that it is not possible to set variables inside a block and have them show up outside of it. This also applies to loops.
As a workaround (in Jina 2.10+), you can use a namespace object to create assignments that propagate to outer scopes:
{% set ns = namespace(has_swimming=false) %}
{% for row in Class['Students'] %}
{# ... #}
{% if hobby == 'SWIMMING' and not ns.has_swimming %}
{% set ns.has_swimming = true %}
{% endif %}
{# ... #}
{% endfor %}
{% if ns.has_swimming %}
{# ... #}
{% endif %}