Jinja2 is the default templating engine used in Flask for rendering dynamic HTML content. It allows embedding Python-like expressions inside HTML, enabling developers to create dynamic and reusable templates. Jinja2 helps in separating the presentation layer from the application logic, making web applications more maintainable.
1. Setting Up Jinja2 in Flask
To use Jinja2, you need a templates folder inside your Flask project. Flask automatically looks for HTML templates in this directory.
Folder Structure
/flask_app
/templates
index.html
about.html
app.py
Basic Flask Application with Jinja2
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def home():
return render_template("index.html", name="John Doe")
if __name__ == "__main__":
app.run(debug=True)
This code sends the variable name
to the template index.html.
2. Jinja2 Syntax
Jinja2 syntax allows us to use expressions, loops, conditionals, and filters inside HTML.
2.1 Variables
Inside templates, variables are enclosed in {{ }}
:
<h1>Welcome, {{ name }}!</h1>
If name = "John Doe"
, the rendered output will be:
<h1>Welcome, John Doe!</h1>
2.2 Control Structures
2.2.1 If-Else Conditions
{% if age >= 18 %}
<p>You are eligible to vote.</p>
{% else %}
<p>You are not eligible to vote.</p>
{% endif %}
2.2.2 For Loops
<ul>
{% for user in users %}
<li>{{ user }}</li>
{% endfor %}
</ul>
If users = ["Alice", "Bob", "Charlie"]
, it will generate:
<ul>
<li>Alice</li>
<li>Bob</li>
<li>Charlie</li>
</ul>
3. Jinja2 Filters
Jinja2 filters modify variables in templates.
3.1 Common Filters
Filter | Description | Example |
---|---|---|
upper | Converts to uppercase | `{{ name |
lower | Converts to lowercase | `{{ name |
title | Capitalizes words | `{{ name |
length | Returns length | `{{ users |
default | Sets default value | `{{ age |
Example: Using Filters
<p>{{ name|upper }}</p>
<p>Number of users: {{ users|length }}</p>
4. Template Inheritance
Jinja2 allows defining a base template and extending it in other templates.
4.1 Creating a Base Template
templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>{% block title %}Flask App{% endblock %}</title>
</head>
<body>
<header>
<h1>My Website</h1>
</header>
<main>
{% block content %}{% endblock %}
</main>
</body>
</html>
4.2 Extending the Base Template
templates/index.html
{% extends "base.html" %}
{% block title %}Home - Flask App{% endblock %}
{% block content %}
<h2>Welcome to My Flask App</h2>
{% endblock %}
5. Including and Reusing Templates
Instead of repeating code, we can include parts of a template.
5.1 Creating a Navbar Component
templates/navbar.html
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
5.2 Including the Navbar in Other Templates
{% include "navbar.html" %}
6. Passing Data from Flask to Jinja2
6.1 Passing Lists
@app.route("/users")
def users():
user_list = ["Alice", "Bob", "Charlie"]
return render_template("users.html", users=user_list)
users.html
<ul>
{% for user in users %}
<li>{{ user }}</li>
{% endfor %}
</ul>
6.2 Passing Dictionaries
@app.route("/profile")
def profile():
user_info = {"name": "John Doe", "age": 25, "city": "New York"}
return render_template("profile.html", user=user_info)
profile.html
<p>Name: {{ user.name }}</p>
<p>Age: {{ user.age }}</p>
<p>City: {{ user.city }}</p>
7. Using Macros in Jinja2
Macros allow reusable template components.
7.1 Creating a Macro
templates/macros.html
{% macro button(text, link) %}
<a href="{{ link }}" class="btn">{{ text }}</a>
{% endmacro %}
7.2 Using the Macro
{% import "macros.html" as macros %}
{{ macros.button("Click Here", "/about") }}
8. Static Files in Jinja2 (CSS & JS)
Flask serves static files from the /static folder.
8.1 Folder Structure
/flask_app
/static
/css
style.css
/js
script.js
/templates
index.html
app.py
8.2 Linking CSS and JavaScript
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<script src="{{ url_for('static', filename='js/script.js') }}"></script>
9. Escaping HTML in Jinja2
Jinja2 automatically escapes special HTML characters to prevent XSS attacks.
Example
<p>{{ "<script>alert('XSS')</script>" }}</p>
Rendered output:
<p><script>alert('XSS')</script></p>
To disable escaping:
<p>{{ "<script>alert('XSS')</script>" | safe }}</p>
10. Debugging in Jinja2
10.1 Showing Debug Information
If a variable is None
, use:
{{ variable or "Default Value" }}
10.2 Using {% set %}
{% set greeting = "Hello, World!" %}
<p>{{ greeting }}</p>