Demystifying Jinja2: The Art of Python Templating

-IMF J050
→ Introduction
Welcome readers to the world of coding! Many of you might be wondering what this blog could be about and what exactly is Jinja? Many of us have heard (or not heard) about coding and have even feared from the web development languages like:
- C/C++
- Python
- Java/JavaScript
- HyperText Markup Language (HTML)
- Extensible Markup Language (XML)
- Cascading Style Sheets (CSS) ...and many more!
But today, we’re diving into something built within the friendly-neighborhood language — Python 🐍. This tool helps us develop web pages, websites, and even combine Python with HTML, XML, LaTeX, and more. So to drive away the fear of web development, Python gives us a Library which is none other than Jinja2 Templating — the secret ingredient for creating dynamic, flexible, and efficient web content.
We understand that not all of our readers may have a background in coding or Python. That’s why this guide is designed to be a simple, user-friendly introduction to the Art of Python Templating — Jinja2 Templating.
→ Contents:
- Pre-requisites for Jinja2 Templating
- Introduction to the Jinja2 Templating
- Installation & Setup of the Jinja2 in Python
- Coding in Jinja2: Connecting Python and HTML
- Displaying texts messages Using Jinja2
- Basic Syntaxes and Functions in Jinja2
- Formatting the Template
- HTML Webpages with Python using Jinja2
- Key Features in Jinja2 Templating
- Variable Substitution:
- Control Structures (Conditionals and Loops)
- Filters
- Macros
- Template Inheritance
- HTML Escaping
- Applications of Jinja2 Templating
- Common Errors faced by Users
- Conclusion
- References
֍ Pre-requisites for Jinja2 Templating:
So to understand the whole content of blog, there are mainly two basic pre-requisites: HTML and Python. If you know basics of Python and HTML5, then you can skip this section and move on to the nect section: "Introduction to the Jinja2 Templating". So, here we will have a basic knowledge of what is HTML5 and Python and will provide necessary links for the basic understanding of both languages:
- Python: Python is a high-level, general-purpose programming language. Its design philosophy emphasizes code readability with the use of significant indentation. It was created by Guido van Rossum, and released in 1991.
It is used for many purposes like:- Web Development (server-side)
- Software Development
- Mathematics
- System Scripting.
- Matplotlib - To plot graphs
- Math - Includes all mathematical functions
- Numpy and Pandas - Helps a lot in Data Visualization
- CSV and Pickle - Helps a lot in managing csv files and binary files
- HTML5: Hypertext Markup Language (HTML) is the standard markup language for documents designed to be displayed in a web browser. It defines the content and structure of web content. It is often assisted by technologies such as Cascading Style Sheets (CSS) and scripting languages such as JavaScript, a programming language.
HTML elements are the building blocks of HTML pages. With HTML constructs, images and other objects such as interactive forms may be embedded into the rendered page. HTML provides a means to create structured documents by denoting structural semantics for text such as headings, paragraphs, lists, links, quotes, and other items.
There are many features of HTML language. Some of them are:- Webpage Development: It helps to create structured content on webpages
- Creating UI (User-Interface) - You can create forms like quizzes, surveys in HTML5 with help of form tag.
- Web Applications - Platforms like Google Docs, Gmail use HTML along with JavaScript frameworks to build dynamic web applications.
- Email templates - It also helps in creating email templates
- API's Development - Through HTML5, API's like Canva have been developed.
- Variable Access
- Control Structures (loops)
- Macros (functions)
- Filters
- Inheritance
- Control structures (loops and conditional statements)
- Rich set of built-in filters and tests
- Template inheritance
- Macros
- Support for custom filters
- HTML escaping
- Easy to debug
- Configurable syntax
֍ Introduction to the Jinja2 Templating:
Jinja2 Templating is a templating engine for Python that allows us to create dynamic webpages, websites by merging Python data with other web developing languages like HTML, XML etc.It is the part of Python library that handles the designs of the webpages. It is a bridge that connects Python's codes to the front-end design that makes the web page look attractive and make it easy to visualize codes easily.
Jinja2 is nothing but just a text rendering engine for Python. It is commonly used in web frameworks like Django, Flask, Quarto , Ansible etc. The basic principle to use Jinja2 is to capture business logic in the code while giving template designer tools to control flow and layout of the end document.
It is very popular because of its easy syntax and variety of features including:
Jinja2 templating in Python helps a lot in Python as it has a great number of features. Some of them are:
The syntax of Jinja2 is heavily influenced by Django and Python making it more familiar for those who know Python very well. Let's see an example that how we will use Jinja2 Templating:
from jinja2 import Template
template = Template("Hello, {{ name }}! Welcome to {{ platform }}.")
output = template.render(name="Pallav", platform="IIT Gandhinagar")
print(output)
Hello, Pallav! Welcome to IIT Gandhinagar.
→ Mechanism (Working) of Jinja2 Template:
So, Jinja2 is a templating engine for Python that helps in dynamically generating content, usually HTML pages, by combining templates with data. In simple words, Jinja2 acts as a bridge between Python data and HTML templates, i.e., we can use html tags within Python codes which will help in designing of webpages using python.
So the basic working of Jinja2 starts with requirement of two core elements:
- Template
- Data
We provide the template and data to the Jinja rendering engine as input which then combines them and gives output as text or text file. So we all have doubt that what is actually this template and data.

So let's discuss them:
- Template: A template is nothing nut just a text file defining the structure of document (that will be processed (rendered)) with Jinja syntax at places where we want to work with data. These are HTML files mixed with Jinja2 syntax that act as placeholders for dynamic data.
There are many key syntaxes in templates like:- {{ ... }} → For inserting variables or expressions
- {% ... %} → For logic statements like loops & conditionals
- {# ... #} → For comments (won't appear in output)
- Data: Data is just the values like dictionary in python, JSON file etc. that has to be inserted into template. Jinja2 doesn't care where the data comes from, this could come from JSON (JavaScript Object Notation) returned by some API (Application Programming Interface) , be loaded from static YAML (YAML Ain't Markup Language) file, or simply be a Python Dict defined in our app.
- Rendering the data: So rendering means that we combine templates and data to get the final document.
So the rendering engine uses the data and plugs it into the template as specified in it to create the output text. The templates do not require any special extension or any extension at all. But it is suggested to use ".jinja" extension because this would be useful to identify the files and if you are using IDEs (Integrated development Environments) this would be useful to make them understand that it is a Jinja file. In exceptional cases, like operating with web Frameworks like Flask or Django, we can use ".html" extension which offers extra advantages in that environment like html escaping.
This was all about the Introduction to the Jinja2 Templating. Let's now start coding in Python and use it to develop beautiful webpages.
֍ Installation & Setup of the Jinja2 in Python:
So, the requirements as per software for Jinja2 Templating are:
- Python:
So firstly we need to have Python programming platform in our computer to start Jinja2 templating. So we can easily download Python by many methods as shown below:- Python IDLE: We can easily download Python from the official website. The link for downloading is given below:
🔗 Link: https://www.python.org/downloads/ - Anaconda Navigator: Anaconda is the hub of all Python Platforms. It includes Spyder IDE, Jupyter Notebook, Jupyter Lab, Powershell, PyScript, and many other platforms, and has a huge number of Python libraries including pandas and matplotlib already installed. This is the most recommended one. The link for download is given below:
🔗 Link: https://www.anaconda.com/download - Visual Studio Code: If we are talking about downloading Python platforms, and forgot to mention the hub of programming, then it is truly unfair. VS Code is the all-in-one platform for all languages starting from C, C++, Java, C#, Python, HTML5, and many more. It has very user-friendly syntax and many snippets that help in fast coding. The link for VS Code is given below:
🔗 Link: https://code.visualstudio.com/download
- Python IDLE: We can easily download Python from the official website. The link for downloading is given below:
- Jinja2 Template: So after installing Python Programming platform, we have to download Jinja2 Template in our platform. We can have various methods to download it but the best methods are two given below:
- Command Prompt/Terminal: So open the command prompt of the Windows or MacBook you are using and add the following code:
# On Windows / MacBook py -m pip install jinja2
And for the Linux, you can use the following snippet:
# On Linux python3 -m pip install jinja2
- Anaconda Navigator: If you are using Anaconda Navigator, then you have to open the base(root) terminal in the environments section and them add the following code to install the Jinja2 Template:
conda install anaconda::jinja2
So, once we are done with the installation, let's check if our Jinja2 is properly setup or not. So for that firstly, let's check it's version:
import jinja2 # import helps to add the required library
print("Jinja2 version:", jinja2.__version__) # .__version__ is used to get version of the library
Jinja2 version: 3.1.5
So we got our version of Jinja2 as 3.1.5. Let's quickly check if it is working or not by writing a very simple code:
from jinja2 import Template
template = Template("Hello, {{ name }}!") # Creating a template
rendered = template.render(name="World") # Rendering (combining) data (world) with template)
print(rendered)
Hello, World!
So if we got this output successfully, we have perfectly set up the Jinja2 Template and are now ready to dive deep into the use of Jinja2 templating for web design.
One thing we should note that:
Jinja2 is widely utilized in web page development, particularly in Python-based web frameworks such as Flask and Django. While Jinja2 is not technically a front-end design software such as CSS or HTML, it is essentially being utilized as a templating engine, which renders HTML content from backend data.
֍ Coding in Jinja2: Connecting Python and HTML
So before going on to the Coding part, we should know that: Rendering a jinja template always results in some text and it invloves the following steps:
- Importing the required libraries/modules like Jinja2 or important functions from it by using from <'module'> import <'function'>.
- Creating a jinja2 rendering environment and store it in a variable. This environment will be used in further steps.
- Load the template in a variable.
- Render the template using <'template-object'>.render() function to obtain text.
- Print the rendered text to the screen or a file as suitable.
So this was the basic steps of how to use Jinja2 templating. Let's now go into coding part:
→ Displaying texts messages Using Jinja2
So follow the steps given below to print required statement using Jinja2:
- Create a folder named Jinja2 Templating where all jinja, python, text files will be stored
- Create a text file of name "Welcome to Jinja" and add the text to be printed (here "Welcome to Python - HTML Interface: Jinja2 Template"
- Save the file as extension .jinja (Extension of jinja2 file)
- Import the library and create an environment variable env which will include the path to folder in which your jinja file is present
- Then render the Jinja file using env,get_template(<'file name'>)
- Print it
from jinja2 import Environment, FileSystemLoader
env = Environment(loader = FileSystemLoader('.')) # . points to the current directory
template = env.get_template('Welcome to Jinja.jinja')
output = template.render()
print(output)
Welcome to Python - HTML Interface: Jinja2 Template
It is important for us to know why we used such functions. So let's understand this code deeply:
Function | Purpose |
---|---|
Environment() | Acts as the core of Jinja2 — manages templates and their settings. |
FileSystemLoader(<path>) | Tells Jinja2 where to find the templates. Points to the template directory. |
env.get_template(<file>) | Fetches the specific template you want to render. |
template.render() | Converts the template into a final text output. |
print(output) | Displays the rendered output on the screen. |
So this is how Jinja2 works:
Template → Render → Output
Suppose if we don't want output in such form and require a text file. Then we can easily convert it into textfile using code:
with open("Welcome_Jinja2.txt", 'w') as f:
print(output, file = f)
And this will create the new file "Welcome_Jinja2.txt" as text file in Jinja2 Templating folder. The format of open( ) is like open(<'Address of folder where rendered file is to be saved.>/<'filename.txt'>)
So now we learnt how to print a Jinja file in python and to store it in text form. Let's see how we cam format the template but before it we should know Basic syntaxing in Jinja2.
→ Basic Syntaxes and Functions in Jinja2
The basic functions and syntaxes that we can do and use in Jinja2 are:
- Delimiters: Delimiters in Jinja2 are special characters that indicate where dynamic content, logic, or expressions should be inserted in templates. They assist Jinja2 in determining static text (such as HTML, which we are soon going to see) and template code. There are mainly three types of delimiters used in Jinja2:
Delimiter Purpose When to use? Example {{...}} It is used to output the variables or run simple expressions, i.e., it functions similar to Python's f string. It is used when we have some function outputs, outputs of variables etc. Hello {{name}}! → <'template'>.render (name = "Salman Khan") → Hello Salman Khan! {%...%} It is used to create loops and conidtional blocks, i.e., for logics in Jinja2 templates.. It is used when we have control structures, loops or conditional blocks (if-elif-else) {% for item in list %} {# ... #} It is used to add comments in the Jinja2 template. It is used when we want to add notes or comments in templates for readers to understand code easily. {# This is a comment #} - Expressions: As we saw in above table, delimiter {{...}} acts as f string. The data which we write inside the {{...}} delimter is called the expressions. We pass expressions in the template and then to get them as output, we render our template.So we can say that expressions are just data of Jinja2 Template.
- Decisions: The conditions if-elif-else come under this category. The syntax of using the conditionals is:
{% if [condition] %} [if block] {% elif [condition2] %} [elif block] <% else %> [else block] <% endif %>
- Loops: So again Jinja2 has for loop which is same as Python. It's syntax is:
{% for [variable name] in [sequence] %} [block inside the loops] {% endfor %}
So the text only inside that respectibe block is executred whose conditions met.
So this was all about the syntax of Jinja2 Template.
→ Formatting the Template
Here, we will learn that if suppose I have a template then how can I add text to it using Python with help of Jinja2. And here we will use the basic syntaxing of Jinja2 which we learnt in previous section.
Now suppose I want to print Hello <'name'>! where name is given by the user using Jinja2. So we can create a template "Hello World" having format "Hello {{name}}!" as {{...}} delimiter works as f string. So the code to format the template "Hello World" will be:
from jinja2 import Environment, FileSystemLoader
# Loading the Environment
env = Environment(loader = FileSystemLoader('.')) # Takes it to the current directory
# Loading the template
template = env.get_template('Hello World.jinja')
# Getting input from the user
n = input("Enter the name to be added in the Jinja file: ")
# Rendering the data and template
output = template.render(name=n)
# Printing the output
print(output)
Hello Pallav Biyala!
We can also create a text file as we created earlier by same method. So now we know how to format template, display Jinja2.
→ HTML Webpages with Python using Jinja2:
Now comes the main part of Jinja2, i.e., HTML formatting in Python using Jinja2
So the concepts which we learnt now are enough to create a HTML Page which can actually render table of a given number. To render an HTML page, we only have to know how to do coding using HTML. So, we just need to have the HTML markup inside the Jinja Template where required and then can save the rendered jinja2 text to an external file with a .html extension. This will create a webpage.
So let's create a jinja file "Table of number n" which will have the following HTML Code:
<!DOCTYPE HTML>
<html>
<head>
<title>Table of {{ '{{ number }}' }}</title>
</head>
<body>
<h3>Table of {{ '{{ number }}' }} rendered with Jinja2 Templating:</h3>
{% raw %}{% for i in range(1, 11) %}{% endraw %}
<p>{{ '{{ number }}' }} × {{ '{{ i }}' }} = {{ '{{ number * i }}' }}</p>
{% raw %}{% endfor %}{% endraw %}
</body>
</html>
And save it as "Table of number n.jinja". Then we can directly write the python code to print table of any number:
from jinja2 import Environment, FileSystemLoader
env = Environment(loader = FileSystemLoader('C:/Programming_Files_Python_C_C++/Python Files/Jinja2 Templating/'))
template = env.get_template('Table of number n.jinja')
output = template.render(number = 10)
print(output)
<!DOCTYPE HTML> <html> <head> <title> Table of 10 </title> </head> <body> <h3> Table of 10 rendered with Jinja2 Templating is:</h3> <p>10 × 1 = 10</p> <p>10 × 2 = 20</p> <p>10 × 3 = 30</p> <p>10 × 4 = 40</p> <p>10 × 5 = 50</p> <p>10 × 6 = 60</p> <p>10 × 7 = 70</p> <p>10 × 8 = 80</p> <p>10 × 9 = 90</p> <p>10 × 10 = 100</p> </body> </html>
And to create a webpage of it, we can convert it into html file by:
with open("C:/Programming_Files_Python_C_C++/Python Files/Jinja2 Templating//Table of number n.html", 'w') as f:
print(output, file = f)
And if we see then in the folder "C:/Programming_Files_Python_C_C++/Python Files/Jinja2 Templating/", a new file Table of number n.html will be formed which will open as a webpage.The output will look like:

The output of the webpage formed can be accessed from here:
Table of number n.html
Now we have a very basic knowledge that how HTML and Python can work hand in hand and Python can be used to create webpages. Let's see more key features of Jinja2 Templating.
Jinja2 Templating provides many features that can be used for many puroposes. Let's see some key features of Jinja2 Templating:
1. Variable Substitution:
We can substitute or insert values of variables into the templates, i.e., we can render them. This is called Variable substitution. We can do this by adding delimiter {{...}} in the HTML Template and then rendering them with data in python using .render().
2. Control Structures (Conditionals and Loops):
We are also familiar with this feature of Jinja2. We can use loops (for) and conditionals (if-elif-else) in our templates and then use .render to fill the values. We successfully created the Multiplication table using it.
So now let's do something creative. Let's create a webpage using the above features in which a student can enter his name and then can add his details of institute and stream in the webpage created. Let's do it!
So create a HTML file "IITian students.jinja" with the following html code:
<!DOCTYPE html>
<html>
<head>
<title>IITian Student Information</title>
<style type="text/css">
body { background-color: #330033; }
p { font-family: 'Baskerville Old Face'; font-size: 18px; color: #9966cc; }
h1 { font-family: 'Baskerville Old Face'; font-size: 20px; color: #9966cc; text-align: center; }
ol { font-family: 'Baskerville Old Face'; font-size: 18px; color: #9966cc; }
</style>
</head>
<body>
<h1>IITian's Student Information</h1>
<form>
<ol>
<li>Name: {{ '{{ name }}' }}</li>
<li>Your Stream:<br>
{% raw %}{% for stream in streams %}{% endraw %}
<input type="radio" name="stream" value="{{ '{{ stream }}' }}"> {{ '{{ stream }}' }}<br>
{% raw %}{% endfor %}{% endraw %}
</li>
<li>IIT Name:<br>
<select name="iit_name">
{% raw %}{% for iit in iit_list %}{% endraw %}
<option value="{{ '{{ iit }}' }}">{{ '{{ iit }}' }}</option>
{% raw %}{% endfor %}{% endraw %}
</select>
</li>
</ol>
</form>
</body>
</html>
The python code will be:
from jinja2 import Environment, FileSystemLoader
# Step 1: Set up Jinja2 Environment
env = Environment(loader=FileSystemLoader('.')) # Current directory
# Step 2: Load the HTML Template
template = env.get_template('IITian students.jinja')
# Step 3: Data to Pass to Template
name = input("Enter your name to be added in file: ")
iits = [
"IIT Bombay", "IIT Delhi", "IIT Roorkee", "IIT Gandhinagar",
"IIT Kanpur", "IIT Kharagpur", "IIT Guwahati", "IIT Indore",
"IIT Ropar", "IIT Hyderabad", "IIT Madras"
]
streams_n = int(input("Enter the number of streams in your IIT: "))
stream = []
for i in range(streams_n):
stream_in_iit = input(f"Enter the name of stream {i+1}: ")
stream.append(stream_in_iit)
data = {
"name": name,
"streams": stream,
"iit_list": iits
}
# Step 4: Render the Template
output = template.render(data)
# Step 5: Save the Rendered HTML
with open("IITian students.html", "w") as file:
file.write(output)
print("HTML File successfully created")
HTML File successfully created
So this will create a new webpage in which student will see his/her name and can enter his/her stream and institute. We could also have taken it very easily to next level by creating a submit button through which user can submit the details.
The webpage formed will look like:

The file created can be accessed from the below link:
IITian students.html
So we saw how creatively we can use the variable insertion and control structures through jinja to create such webpages. Let's move to next feature to create such nice webpages.
3. Filters:
Jinja2 also has the feature in which we can modify variables within the template by using custom filters as well as built-in filters. So like for example if I want that in a variable, only the first letter should be capiltalized, I can do this using filters in template. Also with help of filters, we can convert the text to uppercase, camelcase etc. It is also useful in cases when I want only limited significant digits,i.e., if I want only 2 digits after point, or like round it to 2 decimal places; I can directly use the filters available in Jinja2.
Some examples of filter are:
- {{ username | upper }} → Converts text to uppercase
- {{ price | round(2) }} → Rounds to 2 decimal places
- {{ name|replace("Ram", "Shyam") }} → Replaces Ram with Shyam
- {{ name|truncate(5) }} → Limits the length of character to 5
Let's take an example. We'll create a list which will have a filter such that it will sort all its elements by itself. So the HTML code and python code to perform it is:
<ul>
{% raw %}{% for item in numbers | sort %}{% endraw %}
<li>{{ '{{ item }}' }}</li>
{% raw %}{% endfor %}{% endraw %}
</ul>
from jinja2 import Environment, FileSystemLoader
# Step 1: Set up Jinja2 Environment
env = Environment(loader=FileSystemLoader('.')) # Current directory
# Step 2: Load the Template
template = env.get_template('Filters Use.jinja')
# Step 3: Pass Data to Template
data = {
'numbers': [9, 3, 5, 1, 7, 2]
}
# Step 4: Render the Template with Data
output = template.render(data)
# Step 5: Save the Rendered HTML
with open('sorted_numbers.html', 'w') as file:
file.write(output)
print("Sorted list generated in 'sorted_numbers.html'")
Sorted list generated in 'sorted_numbers.html'
So the webpage formed will have all its elements sorted.
The webpage formed will look like:

The link for the Webpage file is:
Link : sorted_numbers.html
So in simple words, Filters are tools that allow you to modify variables in templates before rendering them. They are similar to functions that can format data, manipulate strings, and perform operations directly inside templates. For more filters, you can refer the following link:
Filters in Jinja2
4. Macros:
Macros are very powerful tools in Jinja2. They are same as functions in programming languages like Python, C/C++ etc. and work on the principle of DRY (Don't Repeat Yourself). They help us to reuse the code and this helps us to make template look cleaner and more efficient to understand. Instead of writing same piece of code again and again, we can create a macro, define how it should run and then call it anytime when we want to use it. It reduces the lines of codes.
The basic syntax of Macros is:
{% raw %}{% macro macro_name(*args, **kwargs) %}{% endraw %}
< macro body >
{% raw %}{% endmacro %}{% endraw %}
Let's see how Macros can be used:
a) Basic Macros:
{% raw %}{% macro greet(name) %}{% endraw %}
<p>Hello, {{ '{{ name }}' }}!</p>
{% raw %}{% endmacro %}{% endraw %}
<!-- Calling the Macro -->
{{ '{{ greet("Pallav") }}' }}
{{ '{{ greet("Sai Krishna") }}' }}
{{ '{{ greet("Ganesh") }}' }}
So the python code to run this code is:
from jinja2 import Environment, FileSystemLoader
# Step 1: Set up Jinja2 Environment
env = Environment(loader=FileSystemLoader('.')) # Current directory
# Step 2: Load the HTML Template
template = env.get_template('Basic Macros.jinja')
# Step 3: Rendering the data into html file
output = template.render()
with open("Basic Macros.html", "w") as file:
file.write(output)
print("HTML File successfully created")
HTML File successfully created
So, we can see that instead of writing code three times to greet three people, we just created a macros function and used it three times to greet three people. So this really reduced the time complexity of program by reducing the number of functions and the lines of code.
The webpage formed will look like:

The link of file formed is:
Link: Basic Macros.html
b) Macros and Control Structures:
So we can also have for loops and if-elif-else in our Macros. Let's take our previous webpage: "IITian students.jinja". In the code of the iit_name, we could also have used Macros by using the following syntax:
{% raw %}{% macro list_items(items) %}{% endraw %}
<ul>
{% raw %}{% for item in items %}{% endraw %}
<li>{{ '{{ item }}' }}</li>
{% raw %}{% endfor %}{% endraw %}
</ul>
{% raw %}{% endmacro %}{% endraw %}
{{ '{{ list_items(["IIT Delhi", "IIT Bombay", "IIT Kanpur", "IIT Gandhinagar"]) }}' }} {# And many more #}
And we know the method of how to run this.
c) Macros and Buttons:
We can also add buttons in our webpages using macros. And if we link it to some other HTML webpage, it'll act as a real google form page. So we can create buttons using Macros using the following code:
{% raw %}{% macro button(text="Click Me", color="blue") %}{% endraw %}
<button style="background-color: {{ '{{ color }}' }};">{{ '{{ text }}' }}</button>
{% raw %}{% endmacro %}{% endraw %}
{{ '{{ button() }}' }}
{{ '{{ button("Submit", "green") }}' }}
So here since in the first one no text and color is given; it will take the default value , i.e., Click Me and color blue. So let's run it:
from jinja2 import Environment, FileSystemLoader
# Step 1: Set up Jinja2 Environment
env = Environment(loader=FileSystemLoader('.')) # Current directory
# Step 2: Load the HTML Template
template = env.get_template('Macros Button.jinja')
# Step 3: Rendering the data into html file
output = template.render()
with open("Macros Button.html", "w") as file:
file.write(output)
print("HTML File successfully created")
HTML File successfully created
So by this way we can create buttons also using macros.
The webpage formed will look like:

The link for the aboce webpage can be accessed from here:
Link: Macros Button.html
So we saw that how macros are such powerful tools in Jinja2 Templating. Macros are great for forms, buttons, cards, and repeating UI elements in web templates. There are many more fucntions of Macros. To refer them, you can use the following website:
Link: Macros in Jinja2
The most powerful part of Jinja is template inheritance. Template Inheritance allows you to create a base template that acts as a blueprint, and then extend it in child templates. This is super useful when you want to maintain a consistent layout (like headers, footers, navbars) across multiple pages but still allow for unique content on each page.
So a template inheritance has two parts:
- Base Template: This is the HTML file that holds the common structure and uses {% block %} tags to define areas that child templates can overwrite while others remain fixed.
- Child Template: This is the template which extends the base template and overrides the defined blocks.
So one thing we should note that Template inheritance of Jinja2 is not same as Macros/ Functions. It's more similar to Object Oriented Programming (OOP) of C++. Here, base template is like a parent class, child template like a subclass overriding methods and {% block %} signifies where child template can actually override. So we can think base templates are blueprints and child templates are inherit from blueprint but can modify its certain parts where {% block %} is present.
To avoid confusion between Functions and template inheritance, let's see differences between them:
Parameter | Functions/ Macros | Template Inheritance |
---|---|---|
Purpose | Reuse a block of code repeatedly. | Reuse a layout or structure across multiple pages. |
Execution | Called when needed | Automatically applied through inheritance |
Analogy | Like a utility in a module, called when required. | Like a parent class, that child class extends |
Customization | Pass arguements to call it | Overrides blocks to customize content |
So let's have an example.
We have a base (parent) template as given below:
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}My Website{% endblock %}</title>
</head>
<body>
<header>
<h1>Welcome to My Website</h1>
</header>
<nav>
<a href="/">Home</a> | <a href="/about">About</a>
</nav>
<div>
{% block content %}{% endblock %}
</div>
<footer>
<p>© 2024 My Website</p>
</footer>
</body>
</html>
And our child template is:
{% raw %}
{% extends "base.html" %}
{% block title %}Home Page{% endblock %}
{% block content %}
<h2>Home Page</h2>
<p>Welcome to the homepage of my awesome website!</p>
{% endblock %}
{% endraw %}
Let's run this code using the following python code:
from jinja2 import Environment, FileSystemLoader
# Set up Jinja2 Environment
env = Environment(loader=FileSystemLoader('.'))
# Load child template
template = env.get_template('Child Template.jinja')
# Render and save
output = template.render()
with open("Rendered child template.html", "w") as file:
file.write(output)
print("Rendered successfully!")
Rendered successfully!
So if everything would be correct, you'll see that you really created a webpage that shows home page. Here, we fixed the heading as the parent template as all pages should has the heading. While the content, i.e., home and about could vary. So we kept that in block content and with help of child template of home page, we extended the parent class and we could see what it showed as output.
The webpage formed will look like:

We can refer the following link to see the webpage:
Link: My Website
To learn more about the Template Inheritance, you can refer the link given below:
Link: Template Inheritance
So these two features: Macros and Template Inheritance are very two popular and powerful features of Jinja2 which helps a lot in Webpage development using Python.
So we discussed almost all the most important features of the Jinja2 Templating. In addition to them, other important features include HTML Escaping, Dynamic Rendering with other databases, API's or files into JSON, or any other text-format.
6. HTML Escaping:
Those familiar with HTML would have faced issues where they wanted to print a text but it included some HTML tags due to which it was interepreted as HTML code and unexpected outputs could have come.
And so to solve it Jinja2 has a very systematic method which we call HTML Escaping.
So HTML Escaping is the process of converting special characters in HTML into their corresponding text to prevent them from being interpreted as actual HTML code. This ensures that the content is displayed as text rather than being executed or interpreted as HTML or JavaScript, which is essential for security (especially to prevent XSS attacks) and for displaying special symbols.
Cross Site Scripting Cross Site Scripting (XSS) is a vulnerability in a web application that allows a third party to execute a script in the user’s browser on behalf of the web application. Cross-site Scripting is one of the most prevalent vulnerabilities present on the web today. The exploitation of XSS against a user can lead to various consequences such as account compromise, account deletion, privilege escalation, malware infection and many more.
HTML Escaping is very important in today's world because of following reasons:
- Security: Prevents malicious code (like JavaScript) from being executed. And this is a common cause for XSS Attacks.
- Correct Display: Ensures that characters like <, >, or & are displayed as it is rather than being interpreted as HTML tags or entities.
- Data Integrity: Helps when user-generated content (like comments or form inputs) is displayed on a webpage.
So some common characters that need HTML Escaping are:
Character | Key to escape | Purpose |
---|---|---|
< | & lt; | Less than symbol |
> | & gt; | Greater than symbol |
& | & amp; | Ampersand |
" | & quot; | Double Quotation mark |
' | & #39; | Single Quotation Mark |
In addition to this, we can also use filters: |safe (to get html tags as it is) and |e or |escape (to manually escape variables).
For more details on HTML Escaping, you can refer the following link: HTML Escaping
A Secret Even in this blog created using Jupyter notebook, the HTML5 Codes have been added using HTML Escaping codes otherwise they were being automatically executed. And as a blogger I want my readers to knwo in detail about the code. That's why I added the HTML5 code and used HTML Escaping cpdes so that they do not get executed and appears as plain text
Jinja2 isn’t just for creating HTML templates—its power lies in its versatility and ability to dynamically generate a wide range of files and data structures. And there are a vast number of applications of Jinja2 in this world of technology:
- Web Development: We can create webpages as well as websites through Flask and Django using Jinja2 templating to render HTML Pages dynamically. It helps in injecting data into webpages
- Email Automation: We can even generate bulk emails with custom names, links and content. This makes Jinja2 useful in marketing campaigns and transactional emails.
- Reports Formation: Jinja2 is used in data analysis for dashboards and summaries.
- Templates driven form: We can even create forms through Jinja2 templating that can include quizzes, surveys, and also feedback forms etc.
- Configuration file generation: It is also used in DevOps and cloud deployments to create multiple configurations file. It is commonly used with Ansible, Terraform etc.
- E-commerce Platforms: Jinja2 also find its application in E-Commerce websites because of its features to render product details, customize emails etc.
- Data Science and Visualization: It has the ability to get integrated with plotly, matplotlib which can help a lot to plot graphs on webpages
So before coming to the end we would like to include all the common errors that you all might face during jinja2 templating. So let's discuss them:
Errors | Causes | How to fix them? |
---|---|---|
TemplateNotFound Error | Occurs when the template file path is incorrect or the template is missing. | Fix:Ensure the template exists in the correct folder and the file path is accurate. |
UndefinedError | This happens when a variable used in the template isn't passed from Python. | Always pass required variables using template.render()and use {{ variable | default('value') }} for fallbacks. |
Improper Use of Control Structures | Forgetting to close blocks like {% if %} or {% for %} | Always close blocks with {% endif %} or {% endfor %} |
HTML Injection (XSS) Vulnerability | Directly rendering user input can make your website vulnerable to attacks. | Jinja2 autoescapes by default, but always validate and sanitize user inputs. |
Incorrect Filter Usage: | Using non-existent filters or incorrect syntax. | Refer to the Official Jinja2 Filter Documentation for proper usage. |
So we really had a very-very long talk on Jinja2 Templating. We firstly saw what it is, why is it used and how it works. Then we went to the part where we can actually understand how it functions and learnt its basics to create a webpage using HTML-Python. Then we went to see its key features and saw main five key features: Variable Insertion, Control Structures, Filters, Macros, and Template Inheritance. There are too many more functions of it like HTML Escaping which helps to protect users from crisis like XSS Attacks; HTML Injection etc.; its integration with Django, Ansible, Flask etc. make it very useful tool.
[To know more about HTML Escaping, you can use the following link: HTML Escaping]
We saw earlier that how Jinja2 was used to plot graph, and just as an example we saw its compilation with Flask. Jinja2 has a wide real world application like in email templates, webpage developments and many other.
So I hope that this blog helped you to have a good base for the Jinja2 Templating and though we couldn't include its intergation with Django, Ansible as that would have made it too advanced.
The journey through Jinja2 Templating doesn't have to end here! While this blog laid the groundwork there's a whole world of advanced tricks, real-world applications and developer secrets waiting for you to explore.
Below are the references that fueled this blog along with references for additional information and all the links that have supported our blog:
Pre-Requisite Resources:
- 🔗 Python 3.13.2 Official Documentation — Useful for learning Python.
- 🔗 Python Programming Language Wikipedia — To know theory of Python Language
- 🔗 What is Python? – W3Schools — To know more about functions and features of Python.
- 🔗 Introduction to HTML5 -Wikipedia — To know what is HTML and have deep insights into it.
- 🔗 HTML5 Bacis -W3 Schools — To learn how to create webpages using HTML5
Jinja2 Essentials:
- 🔗 Jinja2 Tutorial – Part 1: Introduction & Variable Substitution — A deep dive into Jinja2 basics and variable handling.
- 🔗 Getting Started with Jinja Template – GeeksforGeeks — Perfect for beginners exploring Jinja templating.
- 🔗 Best Practices for Jinja Templating – GeeksforGeeks — Tips to write clean and efficient templates.
- 🔗 Jinja2 Official Documentation — The ultimate guide for filters, macros, and inheritance.
- 🔗 Jinja2 Tutorial by ttl255 — Very good and advnaced guide for the Jinja2 Templating
Security & Best Practices:
- 🔗 HTML Injection Tutorial – SoftwareTestingHelp — Understand how HTML Injection works and how to prevent it.
- 🔗 What is Cross-Site Scripting (XSS)? – GeeksforGeeks — Learn about XSS vulnerabilities and prevention techniques.
Advanced Jinja2 Techniques:
- 🔗 How to Use Macros in Jinja – GeeksforGeeks — Master macros for reusability and clean code.
- 🔗 Jinja2 in Dynamic Customer Messaging – Dashly Help Center — Explore how Jinja2 can be used in customer engagement workflows.
Supporting Tools & Downloads:
- 🔗 Visual Studio Code – Official Download — Lightweight IDE for coding Jinja2 templates.
- 🔗 Anaconda Navigator – Official Download — For Jupyter Notebooks and Python libraries.
- 🔗 Python – Official Download — Ensure you have Python installed for Jinja2 scripting.
Additional Resources:
- 🔗 YAML Tutorial – TutorialsPoint — Useful when integrating Jinja2 with Ansible.
- 🔗 What is an API? – GeeksforGeeks — Understand how Jinja2 works with APIs in web apps.
- 🔗 What is JSON? – W3Schools — Essential for passing data between Python and templates.
- 🔗 Templating with flask in Jinja2 -GeekforGeeks — Know how to use Flask with Jinja2 Templating
For deeper dives into web development, you can check out the Flask and Ansible documentation—both heavily use Jinja2 for templating and automation.