Flask - Templates
Flask – Using Templates with Jinja2
Section titled “Flask – Using Templates with Jinja2”While you can return HTML directly as strings from your Flask view functions, this quickly becomes unmanageable and mixes presentation logic with application logic. Flask integrates the powerful Jinja2 templating engine to solve this problem.
Instead of building HTML strings in Python:
Section titled “Instead of building HTML strings in Python:”# Less maintainable approach@app.route('/old')def old_hello(): user = 'Alice' # Embedding HTML directly in Python code return f'<html><body><h1>Hello {user}!</h1></body></html>'You use Jinja2 templates:
Section titled “You use Jinja2 templates:”-
Create HTML files (templates) with special placeholders for dynamic content.
-
Use Flask’s
render_template()function in your view function to render these templates, passing in any necessary data.
The render_template() Function
Section titled “The render_template() Function”To render a template, you import render_template from Flask and call it within your view function, providing the template filename and any variables you want to pass to the template as keyword arguments.
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/hello/<name>')def hello(name): # Renders 'templates/user_greeting.html' # Passes the 'name' variable from the URL to the template # under the variable name 'username'. return render_template('user_greeting.html', username=name)
if __name__ == '__main__': app.run(debug=True)Template Folder
Section titled “Template Folder”By default, Flask looks for templates in a subfolder named templates located in the same directory as your main application script or package.
/your_project app.py /templates user_greeting.html layout.html # ... other templatesJinja2 Syntax Basics
Section titled “Jinja2 Syntax Basics”Jinja2 templates are primarily HTML files containing special delimiters to embed logic and variables:
{{ ... }}for Expressions: Used to print the value of a variable or the result of an expression to the template output. Jinja2 automatically handles HTML escaping for security.{% ... %}for Statements: Used for control structures like loops (for), conditionals (if/elif/else), template inheritance (extends,block), and macros.{# ... #}for Comments: Used for comments that are ignored by the template engine and won’t appear in the final HTML output.
Example Template (templates/user_greeting.html):
Section titled “Example Template (templates/user_greeting.html):”<!DOCTYPE html><html><head> <title>Greeting</title></head><body> {# This is a comment, it won't be rendered #}
{# Print the 'username' variable passed from Flask #} <h1>Hello, {{ username }}!</h1>
<p>Welcome to our application.</p></body></html>Running the example above and navigating to /hello/Bob would render this HTML, replacing {{ username }} with Bob.
Control Structures in Templates
Section titled “Control Structures in Templates”You can use Python-like control structures within {% ... %} blocks.
Conditionals (if/elif/else)
Section titled “Conditionals (if/elif/else)”Flask Code:
Section titled “Flask Code:”@app.route('/grade/<int:score>')def show_grade(score): return render_template('grade_result.html', marks=score)Template (templates/grade_result.html):
Section titled “Template (templates/grade_result.html):”<!DOCTYPE html><html><body> <h1>Exam Result</h1> {% if marks >= 90 %} <p>Grade: A</p> {% elif marks >= 75 %} <p>Grade: B</p> {% elif marks >= 60 %} <p>Grade: C</p> {% else %} <p>Grade: F - Please see instructor.</p> {% endif %}</body></html>Loops (for)
Section titled “Loops (for)”Flask Code:
Section titled “Flask Code:”@app.route('/items')def show_items(): item_list = ['Apple', 'Banana', 'Cherry'] return render_template('item_list.html', items=item_list)Template (templates/item_list.html):
Section titled “Template (templates/item_list.html):”<!DOCTYPE html><html><body> <h1>Available Items</h1> {% if items %} <ul> {% for item in items %} <li>{{ item }}</li> {% endfor %} </ul> {% else %} <p>No items available.</p> {% endif %}</body></html>Template Inheritance
Section titled “Template Inheritance”Jinja2’s most powerful feature is template inheritance. It allows you to define a base layout template (e.g., layout.html) with common elements (header, footer, navigation) and define specific blocks that child templates can override.
Base Template (templates/layout.html):
Section titled “Base Template (templates/layout.html):”<!DOCTYPE html><html><head> <title>{% block title %}My Application{% endblock %}</title> <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"></head><body> <header> <h1>My Website</h1> </header> <main> {% block content %} {# Child templates will put their content here #} {% endblock %} </main> <footer> <p>© 2023 Me</p> </footer></body></html>Child Template (templates/user_greeting.html updated):
Section titled “Child Template (templates/user_greeting.html updated):”{% extends 'layout.html' %}
{% block title %}Greeting for {{ username }}{% endblock %}
{% block content %} <h2>Hello, {{ username }}!</h2> <p>Welcome to our application.</p>{% endblock %}When user_greeting.html is rendered, Jinja2 will:
- Load
layout.html. - Replace the
{% block title %}inlayout.htmlwith the content of the{% block title %}fromuser_greeting.html. - Replace the
{% block content %}inlayout.htmlwith the content of the{% block content %}fromuser_greeting.html.
This promotes code reuse and makes maintaining a consistent look and feel across your application much easier.