Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access parent for loop scope in child template in Jinja2

Tags:

parent.txt

{% for dict in list_of_dictionaries %}
    {% block pick_dictionary_element %}
    {% endblock %}
{% endfor %}

child_one.txt

{% extends "parent.txt" %}
{% block pick_dictionary_element %}
    {{ dict.a }}
{% endblock %}

child_two.txt

{% extends "parent.txt" %}
{% block pick_dictionary_element %}
    {{ dict.b }}
{% endblock %}

Then:

from jinja2 import Template, Environment, FileSystemLoader
e = Environment(loader=FileSystemLoader("./"))
e.get_template("child_one.txt").render(list_of_dictionaries=[{'a': 'a', 'b': 'b'}])

produces an empty output. How can I access the dict var from the parent for loop? I kind of imagined jinja just in-lining the pick_dictionary_element and the child having the for loop scope of its parent?

like image 817
Andrew Cassidy Avatar asked Aug 05 '18 21:08

Andrew Cassidy


1 Answers

The key to what you are trying to do is to use the scoped keyword on your block:

{# parent.txt #}
{% for dict in list_of_dictionaries %}
    {% block pick_dictionary_element scoped %}
    {% endblock %}
{% endfor %}

Why was this hard to debug?

You made the mistake of using the name dict in the loop:

{% for dict in list_of_dictionaries %}

The side effect of this was that the child template did not readily complain, since the symbol dict exists in its context. If instead, you had done something like:

{# parent.txt #}
{% for a_dict in list_of_dictionaries %}
    {% block pick_dictionary_element %}
    {% endblock %}
{% endfor %}

{# child_one.txt #}
{% extends "parent.txt" %}
{% block pick_dictionary_element %}
    {{ a_dict.a }}
{% endblock %}

You would have been told:

jinja2.exceptions.UndefinedError: 'a_dict' is undefined

like image 123
Stephen Rauch Avatar answered Oct 04 '22 20:10

Stephen Rauch