Search code examples
pythonjinja2tornado

How to pass variables from one template to another in Jinja2


As specified in the title, my concern is about how to pass a variable set in a parent Jinja2 template to its child template.

The configuration of the project is the following:

  • I'm using Tornado to build an API.
  • In the app.py script, I associated the endpoint /parent to the class ParentHandler. When a curl GET method is performed, the get() method of the class ParentHandler is executed and renders its result, response (which is a dict) to the template parent.html. I would like to use the rendered HTML code as a header for the child template, so at the end of parent.html, there is a block to display the tags from the child template.
  • In app.py, I associated the endpoint '/child' to the class ChildHanlder. When a curl GET method is performed, the get() method of the class ChildHandler is executed and renders its result, child_content (which is a dict) to the template child.html (I'm not getting ParentHandler's response in ChildHandler, so ChildHandler renders only child_content). The template child.html includes parent.html, so the behavior I'm expecting is child.html to display the HTML code from parent.html (with the values from the dict response provided by ParentHandler, not ChildHandler) and to render its own dict, child_content.

Unfortunately, when I try to perform the described process above, child.html doesn't find response from parent.py.

Here's a code snippet:

app.py

class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r'/parent', ParentHandler),
            (r'/child', ChildHandler)
        ]

        jinja_load = Jinja2Loader(os.path.join(PATH, '/templates'))
        settings = {
            'template_path': os.path.join(PATH, '/templates')
            'template_loader': jinja_load
        }
        tornado.web.Application.__init__(self, handlers, **settings)

parent.py

class ParentHandler(tornado.web.RequestHandler):
    def get(self):
        response = {"status": "200", "val": "some_value"}
        try:
            self.render("parent.html", response=response)
        except:
            self.write(response)

child.py

class ChildHandler(tornado.web.RequestHandler):
    def get(self):
        response = {"status": "200", "data": "some_data"}
        try:
            self.render("child.html", child_content=response)
        except:
            self.write(response)

parent.html

<div>
    {% if response['status'] == 200 %}
        {% set val1 = response.get('val', 0) %}
        <i>{{ val1 }}</i>
    {% endif %}
</div>
{% block child_content %}{% endblock %}

child.html

{% include 'parent.html' %} 
{% from 'parent.html' import val1 %} 
{% block child_content %}
<table>
{% for d in data %}
    <tr>
        <td>{{ d }}</td>
    </tr>
{% endfor %}
{% endblock %}

But I end up with this error when I try to render child.html:

UndefinedError: 'response' is undefined

Can anyone help me please?


Solution

  • You just need to add the with keyword to the include statement, like so:

    {% include 'parent.html' with var1=value1, var2=value2, ... %} 
    

    In your case

    {% include 'parent.html' with response=responseValue %}