In this tutorial, we are going to see one of the distinctive features of jinja templates called jinja template inheritance.

Jinja template inheritance:

The idea of template inheritance is that we are going to design a base template that contains all the common features that belong to all the pages, and then we are going to provide the content specific to each page in a derived template.

Versions:

  • Python 3.8.5
  • Flask 2.0.1

Jinja template inheritance Example:

As part of this example, I am going to implement a header bar, obviously, we want this header bar to appear on all the pages of our application.

Application Structure:

(venv) flask-jinja-inheritance %
.
├── app
│   ├── __init__.py
│   ├── routes.py
│   └── templates
│       ├── header.html
│       ├── index.html
│       └── profile.html
└── jinja-templates.py

Creating generic header page

Here I would like to implement the header page in a way that can integrate every template that I want. Usually, the header should be present on all the pages in the application.

header.html

app/templates/header.html
<html>
    <head>
        <title>My Blog</title>
    </head>
    <body>
    <h2 style="color:#093657">My Blog</h2> <a href="/">Home</a> | <a href="/profile">Profile</a>
        <hr>
        {% block content %} {% endblock %}
    </body>
</html>

On the above, I created a simple header portion with the blog name, containing home and profile page links init, underneath that, created a new jinja construct called {% block content %} to specify the location where all the derived templates need to insert their page-specific content.

Now I have a pretty generic header page, that I can use all for my pages, now I need to prepare index and profile templates by extending this.

Preparing index.html with a simple welcome message.

app/templates/index.html
{% extends "header.html" %}

{% block content %}
<h1 style="color:#093657"> Welcome
    {% if user %}
        {{user.name}}
    {% else %}
        Buddy!
    {% endif %}
</h1>
{% endblock %}

The way I am linking this index template with the header template is through the extends construct {% extends "header.html"%} and then I provided the content that specific to this page in block content {% block content %} is the same name which we specified in the header template.

Now let’s prepare the profile page with some more information about the user.

profile.html

app/templates/profile.html
{% extends "header.html" %}

{% block content %}
Hobbies:
<div>
    <p><ul>
        {% for hobby in profile.hobbies %}
        <li>{{hobby}}</li>
        {% endfor %}
   </ul></p>
</div>
Interested Books:
<div>
    <p><ul>
        {% for key in profile.interested_books %}
            {{key}}
            <ul>
            {% for book in profile.interested_books.get(key)%}
                <li>{{book}}</li>
            {% endfor %}
            </ul>
        {% endfor %}
   </ul></p>
</div>
{% endblock %}

Create routes.py

app/routes.py
from app import app
from flask import render_template

@app.route('/')
def index():
    user_info = {
        'name':'Chandra'
    }
    return render_template('index.html', user=user_info)


@app.route('/profile')
def profile():
    user = {
        'name': 'Chandra'
    }
    profile = {
        'hobbies':['Blogging','Reading Books','Playing chess'],
        'interested_books':{
            'Java':['Thinking in Java','Inside the Java virtual machine'],
            'Python':['Fluent Python']
        }
    }
    return render_template('profile.html', user=user, profile=profile)

On the above routes.py I have two routes representing index.html and profile.html

When I pass the index.html or profile.html to the render_template() function it’s going to find that there is a reference to a base template (header template) so that it’s going render the header template in the place where the empty block content {% block content %} {% endblock %} and it’s going to put the contents that we have in the profile/index pages.

Now let’s try run this:

Flask - Jinja Template inheritance Example home

There you can see our header section and home page content. Now try access Profile page

Flask - Jinja Template inheritance Example profile

 

References:

Happy Learning 🙂