Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Jinja2 e template(s)

I template

Finora le nostre funzioni restituivano semplici stringhe di testo. In una vera applicazione web vogliamo restituire pagine HTML complete. Potremmo costruire l’HTML direttamente in Python:

@app.route('/')
def home():
    return '<html><body><h1>Ciao!</h1></body></html>'

Funziona, ma diventa presto ingestibile. I template risolvono questo problema: sono file HTML separati, con la possibilità di inserire dati dinamici al loro interno.

Flask usa il motore di template Jinja2, che è già incluso nell’installazione di Flask.

Struttura delle cartelle

Flask si aspetta che i template siano nella cartella templates, nella stessa directory di app.py:

progettoFlask/
├── app.py
└── templates/
    └── index.html

Crea la cartella templates e al suo interno il file index.html:

<!DOCTYPE html>
<html lang="it">
<head>
    <title>La mia prima pagina</title>
</head>
<body>
    <h1>Ciao, Flask!</h1>
</body>
</html>

Per restituire questo template da Flask si usa la funzione render_template:

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    return render_template('index.html')

Flask troverà automaticamente il file nella cartella templates.

Passare dati al template

Il vantaggio dei template è che possiamo passare dati da Python all’HTML. Si usa il secondo argomento di render_template:

@app.route('/')
def home():
    return render_template('index.html', nome='Marco', eta=17)

Modifica il body del file HTML in questo modo: le variabili si usano con la sintassi {{ variabile }}:

<body>
    <h1>Ciao, {{ nome }}!</h1>
    <p>Hai {{ eta }} anni.</p>
</body>

Possiamo passare anche strutture dati più complesse, come liste e dizionari:

@app.route('/')
def home():
    studenti = ['Alice', 'Bruno', 'Carla']
    return render_template('index.html', studenti=studenti)

Esercizi

Esercizio f121

Crea un template profilo.html e una route /profilo che passi al template il tuo nome, la tua città e un numero a piacere. Mostra queste informazioni in una pagina HTML ben formattata.


Esercizio f122

Applicazione con due template(s): la pagina iniziale ha due link: “/saluta/Matteo” e “/saluta/Giovanna”. La pagina saluta raccoglie il secondo parametro del link e lo visualizza scrivendo: ciao <nome>!


Logica nei template

Condizioni

Jinja2 permette di inserire istruzioni condizionali nel template con la sintassi {% %}:

{% if eta >= 18 %}
    <p>Sei maggiorenne.</p>
{% else %}
    <p>Sei minorenne.</p>
{% endif %}

Nota i due tipi di delimitatori:

  • {{ }} — per visualizzare il valore di una variabile
  • {% %} — per istruzioni come if, for, extends…

Cicli

Per scorrere una lista si usa for:

<ul>
{% for studente in studenti %}
    <li>{{ studente }}</li>
{% endfor %}
</ul>

Jinja2 mette a disposizione alcune variabili utili all’interno del ciclo:

{% for studente in studenti %}
    <p>{{ loop.index }} - {{ studente }}</p>
{% endfor %}
VariabileValore
loop.indexIndice corrente (parte da 1)
loop.index0Indice corrente (parte da 0)
loop.firstTrue se è il primo elemento
loop.lastTrue se è l’ultimo elemento

Iterare su dizionari

Possiamo passare anche dizionari e iterare sulle loro chiavi e valori:

@app.route('/prodotto')
def prodotto():
    info = {
        'nome': 'Zaino',
        'prezzo': 29.90,
        'disponibile': True
    }
    return render_template('prodotto.html', info=info)
<dl>
{% for chiave, valore in info.items() %}
    <dt>{{ chiave }}</dt>
    <dd>{{ valore }}</dd>
{% endfor %}
</dl>

Oppure accedendo direttamente ai campi:

<h2>{{ info.nome }}</h2>
<p>Prezzo: {{ info.prezzo }} €</p>
{% if info.disponibile %}
    <p>Disponibile</p>
{% else %}
    <p>Non disponibile</p>
{% endif %}

Esercizi

Esercizio f131

Crea una route /classe che passi al template una lista di almeno 5 nomi di studenti. Il template deve mostrarli in una lista numerata usando loop.index.


Esercizio f132

Modifica l’esercizio precedente: evidenzia in grassetto il primo e l’ultimo elemento della lista usando loop.first e loop.last.

Tip

usa {% if loop.first or loop.last %} per applicare un tag <strong>.


Esercizio f133

Crea una route /voti che passi al template un dizionario con almeno 4 materie e il relativo voto (es. {'Matematica': 8, 'Italiano': 7, ...}). Il template deve mostrare le materie e i voti in una tabella HTML, colorando in rosso i voti inferiori a 6.

Tip

per il colore puoi usare uno stile inline: style="color: red" dentro un {% if %}.


Ereditarietà dei template

Immagina di lavorare ad un sito con dieci pagine, ognuna con la stessa navbar e lo stesso footer. Se vuoi modificare la navbar, devi aprire dieci file. L’ereditarietà dei template risolve questo problema.

Il template base

Si crea un file base.html che contiene la struttura comune a tutte le pagine. Le parti che cambieranno da pagina a pagina vengono definite come blocchi:

<!DOCTYPE html>
<html lang="it">
<head>
    <title>{% block titolo %}Il mio sito{% endblock %}</title>
</head>
<body>

    <nav>
        <a href="/">Home</a> |
        <a href="/about">Chi siamo</a>
    </nav>

    <main>
        {% block contenuto %}{% endblock %}
    </main>

    <footer>
        <p>© 2026 Progetto Flask</p>
    </footer>

</body>
</html>

Il blocco {% block nome %}{% endblock %} è un segnaposto: ogni pagina figlia potrà riempirlo con il proprio contenuto.

Le pagine figlie

Una pagina figlia estende il template base e sovrascrive solo i blocchi che le interessano:

{% extends 'base.html' %}

{% block titolo %}Home{% endblock %}

{% block contenuto %}
    <h1>Benvenuto!</h1>
    <p>Questa è la pagina principale.</p>
{% endblock %}

Tutto il resto — navbar, footer, struttura HTML — viene ereditato automaticamente da base.html.

Un altro esempio per la pagina “Chi siamo”:

{% extends 'base.html' %}

{% block titolo %}Chi siamo{% endblock %}

{% block contenuto %}
    <h1>Chi siamo</h1>
    <p>Questo è il corso di Informatica per le quinte di Scienze Applicate.</p>
{% endblock %}

Struttura finale delle cartelle

progettoFlask/
├── app.py
└── templates/
    ├── base.html
    ├── index.html
    ├── about.html
    └── ...

Esercizi

Esercizio f141 Crea un template base.html con una navbar che contenga i link a / e /about. Crea poi due pagine figlie index.html e about.html che estendano il base e abbiano contenuti diversi. Collega tutto in app.py con le relative route.


Esercizio f142 Aggiungi al template base un terzo blocco chiamato {% block sottotitolo %} posizionato sotto il titolo principale. Nella pagina index.html inserisci un sottotitolo, nella pagina about.html lascialo vuoto (non sovrascrivere il blocco) e verifica che non compaia nulla.