Templates and Jinja2
In Flask, templates are files (usually HTML) that serve as the foundation for rendering dynamic web pages. Flask integrates the Jinja2 templating engine to allow developers to embed Python code within templates and dynamically generate content based on server-side logic.
What Are Templates?
Templates are used to separate the presentation layer (HTML and UI logic) from the business logic (Python code). They are a way to render HTML dynamically by combining static content (HTML structure) with dynamic data (passed from the server).
For example, instead of writing static HTML:
<h1>Welcome, Abhishek!</h1>
A Flask template allows you to dynamically insert the user's name:
<h1>Welcome, {{ username }}!</h1>
This ensures reusability and separation of concerns, making the application easier to maintain.
Flask and Jinja2
Flask uses the Jinja2 templating engine by default. Jinja2 provides:
- Template rendering: Insert dynamic content into HTML.
- Control structures: Use loops and conditionals within templates.
- Template inheritance: Reuse common layout files across multiple pages.
- Filters: Modify or format data before rendering.
Folder Structure for Templates
Flask looks for template files in the templates/
directory by default. A typical folder structure might look like this:
project/
├── templates/
│ ├── base.html
│ ├── home.html
│ ├── about.html
├── static/
│ ├── css/
│ │ └── styles.css
│ ├── js/
│ │ └── app.js
├── app.py
templates/
: Contains all template files.base.html
: A common base layout file.home.html
,about.html
: Specific templates for different pages.
Rendering Templates
Flask provides the render_template
function to render templates and return HTML responses to the client.
Syntax
from flask import render_template
render_template(template_name, **context)
template_name
: The name of the template file (e.g.,home.html
).context
: Key-value pairs passed to the template for dynamic rendering.
Example: Basic Template Rendering
File: app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def home():
return render_template('home.html', username='Abhishek')
if __name__ == '__main__':
app.run(debug=True)
File: templates/home.html
<!DOCTYPE html>
<html>
<head>
<title>Home Page</title>
</head>
<body>
<h1>Welcome, {{ username }}!</h1>
</body>
</html>
- The
username
variable is passed to the template and rendered dynamically. - The output will be: "Welcome, Abhishek!"
Features of Flask Templates
Template Variables
Variables passed from the Flask application to the template are accessible using {{ variable_name }}
.
Example:
@app.route('/user/<name>')
def user(name):
return render_template('user.html', name=name)
File: templates/user.html
<h1>Hello, {{ name }}!</h1>
- URL
/user/Abhishek
will render: "Hello, Abhishek!"
Control Structures
Jinja2 templates support loops and conditionals.
Loops
Example:
@app.route('/items')
def items():
items = ['Apple', 'Banana', 'Cherry']
return render_template('items.html', items=items)
File: templates/items.html
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
-
Output:
<ul>
<li>Apple</li>
<li>Banana</li>
<li>Cherry</li>
</ul>
Conditionals
Example:
@app.route('/check/<int:score>')
def check(score):
return render_template('check.html', score=score)
File: templates/check.html
{% if score >= 50 %}
<p>Pass</p>
{% else %}
<p>Fail</p>
{% endif %}
- URL
/check/60
will render: "Pass" - URL
/check/40
will render: "Fail"
Template Inheritance
Template inheritance allows you to create a base template with common structure and reuse it in other templates.
File: templates/base.html
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}My Flask App{% endblock %}</title>
<link
rel="stylesheet"
href="{{ url_for('static', filename='css/styles.css') }}"
/>
</head>
<body>
<header>
<h1>Flask App Header</h1>
</header>
<main>{% block content %}{% endblock %}</main>
<footer>
<p>Footer content</p>
</footer>
</body>
</html>
File: templates/home.html
{% extends 'base.html' %} {% block title %}Home Page{% endblock %} {% block
content %}
<p>Welcome to the homepage!</p>
{% endblock %}
File: templates/about.html
{% extends 'base.html' %} {% block title %}About Page{% endblock %} {% block
content %}
<p>This is the about page.</p>
{% endblock %}
- The
base.html
file contains the common structure (header, footer, etc.). - The child templates (
home.html
,about.html
) define specific content for their respective pages.
Filters
Filters modify the output of variables. Some commonly used filters include:
upper
: Converts text to uppercase.lower
: Converts text to lowercase.length
: Returns the length of a variable.
Example:
<p>{{ name.upper() }}</p>
<p>{{ description | lower }}</p>
<p>Length: {{ items | length }}</p>
Comments
Comments in Jinja2 templates are not rendered in the final output.
Syntax:
{# This is a comment #}
Passing Context to Templates
Flask supports passing multiple key-value pairs to templates.
Example:
@app.route('/dashboard')
def dashboard():
user = {'name': 'Abhishek', 'age': 30}
stats = {'posts': 15, 'followers': 200}
return render_template('dashboard.html', user=user, stats=stats)
File: templates/dashboard.html
<h1>Welcome, {{ user.name }}!</h1>
<p>Age: {{ user.age }}</p>
<p>Posts: {{ stats.posts }}</p>
<p>Followers: {{ stats.followers }}</p>
Best Practices for Flask Templates
-
Use Template Inheritance:
- Create a base layout for consistent design across pages.
-
Organize Templates:
- Place related templates in subdirectories (e.g.,
templates/users/profile.html
).
- Place related templates in subdirectories (e.g.,
-
Avoid Business Logic in Templates:
- Templates should focus on presentation, not logic.
-
Use Filters for Formatting:
- Format dates, numbers, and strings using filters.
-
Use
url_for
for URLs:- Avoid hardcoding URLs in templates.
Example: A Complete Flask App with Templates
Folder Structure
project/
├── templates/
│ ├── base.html
│ ├── home.html
│ ├── about.html
├── app.py
File: app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def home():
return render_template('home.html')
@app.route('/about')
def about():
return render_template('about.html')
if __name__ == '__main__':
app.run(debug=True)
File: templates/base.html
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}Flask App{% endblock %}</title>
</head>
<body>
<header>
<h1>My Flask App</h1>
</header>
<main>{% block content %}{% endblock %}</main>
<footer>
<p>Footer content</p>
</footer>
</body>
</html>
File: templates/home.html
{% extends 'base.html' %} {% block title %}Home Page{% endblock %} {% block
content %}
<h1>Welcome to the homepage!</h1>
{% endblock %}
File: templates/about.html
{% extends 'base.html' %} {% block title %}About Us{% endblock %} {% block
content %}
<h1>About This App</h1>
<p>This is a Flask application demonstrating templates.</p>
{% endblock %}