Search code examples
flaskjinja2

Flask/Jinja, Multiple Template Inheritance, cannot inherit a block across multiple templates


I'm working on a Flask application with Jinja templating. I have a base template (base.html) that defines several blocks for content and includes other templates like header.html, menu.html, and footer.html.

Within MyPage.html, I'm extending the base.html and defining a block named test1 with some content (test1). However, the rendered output only shows "test1=" with no content.

Here are the relevant code snippets:

App.py

...
@globals.app.route('/MyPage')
def MyPage():
    if os.path.exists(os.path.join(globals.app.root_path, 'templates/pages/MyPage.html')):
        return render_template('pages/MyPage.html')
    else:
        return jsonify({'error': 'Real time test trade page not found'}), 404
...
        

MyPage.html

{% extends 'base.html' %}

{% block test1 %}test1{% endblock %}
...

base.html

<!DOCTYPE html>
<html>
    {% include 'header.html' %}
    <body>
        <div class="container">
            <h1 class="text-center my-4">{% block header %}{% endblock %}</h1>
            {% include 'menu.html' %}
            {% block content %}{% endblock %}
        </div>
    </body>
    {% include 'footer.html' %}
</html>

header.html

<head>
    ...
    <title>{% block title %}{% endblock %}</title>
    ...
</head>
test1={% block test1 %}{% endblock %}

hierarchy

...
|
+---templates
|   |   body.html
|   |   footer.html
|   |   header.html
|   |   menu.html
|   |
|   \---pages
|           MyPage.html
...

I expected to see test1=test1, but now it is test1= (empty).

If I try to move {% block test1 %}test1{% endblock %} from MyPage.html to base.html, it works (test1=test1). However, in this case, the entire purpose of template programming is lost (I mean that you are forced to duplicate the code), so I would still prefer to use a template.

Could you please tell me how to fix my code so that the block {% block test1 %}{% endblock %} in header.html is rendered from the value set in the block {% block test1 %}test1{% endblock %} in MyPage.html?


Solution

  • For now, the best solution seems to be using macros:

    MyPage.html

    {% import 'header.html' as header %}
    {% extends 'base.html' %}
    
    {% block header %}
    {{ header.header("test1", "My Page") }}
    {% endblock %}
    

    base.html

    <!DOCTYPE html>
    <html>
        {% block header %}{% endblock %}
        <body>
            <div class="container">
                <h1 class="text-center my-4">{% block h1 %}{% endblock %}</h1>
                {% include 'menu.html' %}
                {% block content %}{% endblock %}
            </div>
        </body>
        {% include 'footer.html' %}
        {% block temp1 %}{% endblock %}
    </html>
    

    header.html

    {% macro header(value, title) %}
    <head>
    ...
        <title>{{title}}</title>
    ...
    </head>
        test1={{ value }}
    {% endmacro %}