📄 Modulo 3: Templates HTML e Jinja2

Separa la logica dal design: crea pagine HTML professionali

📚

MODULO
3 di 8

⏱️

TEMPO
60 minuti

🎯

LIVELLO
Intermedio

🤔 Il Problema: HTML nel Codice Python

Finora abbiamo restituito HTML come stringhe dentro le funzioni Python. Questo approccio ha grossi problemi:

❌ Approccio SBAGLIATO
@app.route('/')
def home():
    return '''
    <html>
        <head>
            <title>Il Mio Sito</title>
            <style>
                body { font-family: Arial; }
                h1 { color: blue; }
            </style>
        </head>
        <body>
            <h1>Benvenuto</h1>
            <p>Questo è molto scomodo!</p>
        </body>
    </html>
    '''

⚠️ Problemi di questo approccio:

Illeggibile
HTML e Python mescolati
No Syntax Highlight
L'editor non colora l'HTML
Difficile da mantenere
Modifiche complicate
No Riutilizzo
Codice duplicato ovunque

✅ La Soluzione: Templates

I templates sono file HTML separati che Flask carica e "riempie" con i dati. Così:

  • Python gestisce la logica (route, database, calcoli)
  • HTML gestisce la presentazione (layout, stile)
  • Jinja2 fa da ponte, inserendo i dati Python nell'HTML

📁 Struttura delle Cartelle

Flask cerca i templates in una cartella specifica chiamata templates. Questa cartella DEVE essere allo stesso livello di app.py.

📂 Struttura del Progetto
flask-corso/
│
├── app.py              ← File Python principale
│
├── templates/          ← Cartella per i file HTML
│   ├── index.html
│   ├── about.html
│   └── contatti.html
│
└── venv/              ← Ambiente virtuale (non toccare)

1
Crea la cartella templates

In PyCharm:

  • Clic destro sulla cartella del progetto (quella con app.py)
  • New → Directory
  • Digita: templates
  • Premi Invio

⚠️ IMPORTANTE: Nome Obbligatorio

La cartella DEVE chiamarsi esattamente templates (minuscolo, plurale). Flask la cerca automaticamente con questo nome. Se la chiami diversamente, non funzionerà!

🎨 Il Tuo Primo Template

Creiamo il nostro primo template HTML separato.

1
Crea il file index.html

Nella cartella templates:

  • Clic destro su templates
  • New → File
  • Digita: index.html

2
Scrivi il codice HTML

Nel file templates/index.html, digita:

📄 templates/index.html
<!DOCTYPE html>
<html lang="it">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Homepage</title>
</head>
<body>
    <h1>Benvenuto nel mio sito!</h1>
    <p>Questo è il mio primo template Flask.</p>
</body>
</html>

3
Modifica app.py per usare il template

Nel file app.py, cambia il codice in questo modo:

📄 app.py
from flask import Flask, render_template

app = Flask(__name__)

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

if __name__ == '__main__':
    app.run(debug=True)

4
Testa l'applicazione

Avvia il server e vai su http://localhost:5000

Vedrai la pagina HTML caricata dal template! 🎉

🔍 Cosa fa render_template()?

render_template('index.html') dice a Flask:

  1. Vai nella cartella templates/
  2. Trova il file index.html
  3. Leggilo e restituiscilo al browser

🔧 Jinja2: Il Motore di Template

Jinja2 è il linguaggio che Flask usa nei templates. Ti permette di inserire variabili Python, creare cicli, condizioni e molto altro direttamente nell'HTML.

🎯 Sintassi Fondamentale di Jinja2

Sintassi Scopo Esempio
{{ variabile }} Stampa una variabile {{ nome }}
{% istruzione %} Esegue logica (if, for, ecc.) {% if utente %}
{# commento #} Commento (non visibile) {# Questo è un commento #}

💬 Passare Variabili ai Templates

Ora vediamo come passare dati da Python ai templates HTML.

1
Modifica app.py

📄 app.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    nome = "Mario"
    eta = 25
    citta = "Roma"
    
    return render_template('index.html', 
                         nome=nome, 
                         eta=eta, 
                         citta=citta)

if __name__ == '__main__':
    app.run(debug=True)

2
Modifica templates/index.html

📄 templates/index.html
<!DOCTYPE html>
<html lang="it">
<head>
    <meta charset="UTF-8">
    <title>Homepage</title>
</head>
<body>
    <h1>Benvenuto {{ nome }}!</h1>
    <p>Hai {{ eta }} anni e vivi a {{ citta }}.</p>
</body>
</html>

Risultato nel browser: "Benvenuto Mario! Hai 25 anni e vivi a Roma."

💡 Sintassi Alternativa (più pulita)

Puoi passare variabili in modo più compatto:

return render_template('index.html', 
                     nome="Mario", 
                     eta=25, 
                     citta="Roma")

📋 Passare Liste e Dizionari

Puoi passare anche strutture dati complesse come liste e dizionari.

📄 app.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    utente = {
        'nome': 'Mario',
        'cognome': 'Rossi',
        'email': 'mario@email.com'
    }
    
    hobby = ['Calcio', 'Cinema', 'Lettura']
    
    return render_template('index.html', 
                         utente=utente, 
                         hobby=hobby)

if __name__ == '__main__':
    app.run(debug=True)

📄 templates/index.html
<!DOCTYPE html>
<html lang="it">
<head>
    <meta charset="UTF-8">
    <title>Profilo</title>
</head>
<body>
    <h1>Profilo di {{ utente.nome }} {{ utente.cognome }}</h1>
    <p>Email: {{ utente.email }}</p>
    
    <h2>Hobby:</h2>
    <p>Primo hobby: {{ hobby[0] }}</p>
</body>
</html>

🔍 Accesso ai Dati

  • Dizionari: {{ utente.nome }} o {{ utente['nome'] }}
  • Liste: {{ hobby[0] }} (primo elemento)

🔄 Cicli For nei Templates

Jinja2 permette di creare cicli per iterare su liste e dizionari.

📄 app.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    prodotti = [
        {'nome': 'Laptop', 'prezzo': 899},
        {'nome': 'Mouse', 'prezzo': 25},
        {'nome': 'Tastiera', 'prezzo': 45},
        {'nome': 'Monitor', 'prezzo': 199}
    ]
    
    return render_template('index.html', prodotti=prodotti)

if __name__ == '__main__':
    app.run(debug=True)

📄 templates/index.html
<!DOCTYPE html>
<html lang="it">
<head>
    <meta charset="UTF-8">
    <title>Prodotti</title>
</head>
<body>
    <h1>I Nostri Prodotti</h1>
    
    <ul>
    {% for prodotto in prodotti %}
        <li>
            {{ prodotto.nome }} - €{{ prodotto.prezzo }}
        </li>
    {% endfor %}
    </ul>
</body>
</html>

🔍 Variabili Speciali nei Loop

Variabile Descrizione
loop.index Indice corrente (parte da 1)
loop.index0 Indice corrente (parte da 0)
loop.first True se è il primo elemento
loop.last True se è l'ultimo elemento
loop.length Numero totale di elementi
📄 Esempio con loop.index
<ul>
{% for prodotto in prodotti %}
    <li>
        #{{ loop.index }} - {{ prodotto.nome }}
        {% if loop.first %}⭐ PIÙ VENDUTO{% endif %}
    </li>
{% endfor %}
</ul>

❓ Condizioni If/Else

Puoi usare condizioni per mostrare o nascondere parti del template.

📄 app.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    utente_loggato = True
    nome_utente = "Mario"
    eta = 17
    
    return render_template('index.html',
                         loggato=utente_loggato,
                         nome=nome_utente,
                         eta=eta)

if __name__ == '__main__':
    app.run(debug=True)

📄 templates/index.html
<!DOCTYPE html>
<html lang="it">
<head>
    <meta charset="UTF-8">
    <title>Homepage</title>
</head>
<body>
    {% if loggato %}
        <h1>Benvenuto {{ nome }}!</h1>
        <p>Sei loggato nel sistema.</p>
    {% else %}
        <h1>Benvenuto Visitatore</h1>
        <p>Effettua il login per accedere.</p>
    {% endif %}
    
    <hr>
    
    {% if eta >= 18 %}
        <p>✅ Sei maggiorenne</p>
    {% else %}
        <p>❌ Sei minorenne</p>
    {% endif %}
</body>
</html>

Operatori di Confronto

Operatori Disponibili
== Uguale {% if eta == 18 %}
!= Diverso {% if nome != "Admin" %}
> < Maggiore/Minore {% if eta > 18 %}
>= <= Maggiore o uguale / Minore o uguale {% if prezzo >= 100 %}
and or Operatori logici {% if eta > 18 and loggato %}
not Negazione {% if not loggato %}
in Contenuto in {% if "admin" in ruoli %}

🎨 Filtri Jinja2

I filtri modificano le variabili prima di visualizzarle. Si applicano con il simbolo | (pipe).

📄 templates/index.html - Esempi di Filtri
<!DOCTYPE html>
<html lang="it">
<head>
    <meta charset="UTF-8">
    <title>Filtri</title>
</head>
<body>
    <h1>{{ nome|upper }}</h1>           <!-- MARIO -->
    <p>{{ nome|lower }}</p>             <!-- mario -->
    <p>{{ nome|capitalize }}</p>        <!-- Mario -->
    <p>{{ nome|title }}</p>             <!-- Mario Rossi -->
    
    <p>{{ descrizione|truncate(50) }}</p> <!-- Tronca a 50 caratteri -->
    
    <p>{{ lista|length }}</p>           <!-- Numero di elementi -->
    
    <p>{{ prezzo|round(2) }}</p>        <!-- Arrotonda a 2 decimali -->
    
    <p>{{ testo|safe }}</p>             <!-- Non escapa HTML -->
</body>
</html>

Filtro Scopo Esempio
|upper MAIUSCOLO {{ nome|upper }}
|lower minuscolo {{ nome|lower }}
|capitalize Prima lettera maiuscola {{ nome|capitalize }}
|title Ogni Parola Maiuscola {{ testo|title }}
|length Lunghezza lista/stringa {{ lista|length }}
|default('val') Valore di default se vuoto {{ nome|default('Ospite') }}
|join(',') Unisce lista con separatore {{ tags|join(', ') }}
|safe Non escapa HTML {{ contenuto_html|safe }}

🏗️ Template Inheritance (Ereditarietà)

L'ereditarietà dei template ti permette di creare un layout base (header, footer, menu) e riutilizzarlo in tutte le pagine. Questo evita duplicazione di codice!

🎯 Il Concetto

Immagina un palazzo:

  • base.html = struttura del palazzo (muri, finestre, porte)
  • home.html, about.html = appartamenti interni (arredi diversi, ma struttura uguale)
1
Crea il file base.html

📄 templates/base.html - Template Base
<!DOCTYPE html>
<html lang="it">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}Sito Flask{% endblock %}</title>
    <link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
    <header>
        <nav>
            <a href="/">Home</a>
            <a href="/about">About</a>
            <a href="/contatti">Contatti</a>
        </nav>
    </header>
    
    <main>
        {% block content %}
        <!-- Il contenuto delle pagine figlie va qui -->
        {% endblock %}
    </main>
    
    <footer>
        <p>© 2024 Il Mio Sito Flask</p>
    </footer>
</body>
</html>

🔑 Note importanti:

  • {% block title %}{% endblock %} → Area per il titolo della pagina
  • {% block content %}{% endblock %} → Area per il contenuto principale
  • Header e Footer sono FISSI in tutte le pagine
2
Crea home.html che estende base.html

📄 templates/home.html - Pagina Home
{% extends "base.html" %}

{% block title %}Homepage - Il Mio Sito{% endblock %}

{% block content %}
    <h1>Benvenuto nella Homepage!</h1>
    <p>Questo è il contenuto specifico della homepage.</p>
    <p>Data attuale: {{ data_attuale }}</p>
    
    <div class="features">
        <h2>Le Nostre Caratteristiche:</h2>
        <ul>
            {% for feature in features %}
                <li>{{ feature }}</li>
            {% endfor %}
        </ul>
    </div>
{% endblock %}

🔑 Cosa succede:

  • {% extends "base.html" %} → Dice a Jinja2 di usare base.html come template
  • {% block title %} → Sostituisce il titolo nel base.html
  • {% block content %} → Inserisce questo contenuto nell'area "content"
3
Modifica app.py per renderizzare la nuova pagina

📄 app.py - Route per la homepage
from flask import Flask, render_template
from datetime import datetime

app = Flask(__name__)

@app.route('/')
def home():
    # Dati da passare al template
    features = [
        "Templates con Jinja2",
        "Design responsive",
        "Database integrato",
        "API REST"
    ]
    
    return render_template('home.html',
                         data_attuale=datetime.now().strftime("%d/%m/%Y"),
                         features=features)

if __name__ == '__main__':
    app.run(debug=True)

4
Crea about.html per vedere la riusabilità

📄 templates/about.html - Pagina About
{% extends "base.html" %}

{% block title %}Chi Siamo - Il Mio Sito{% endblock %}

{% block content %}
    <h1>Chi Siamo</h1>
    <p>Siamo un'azienda specializzata in sviluppo web con Flask.</p>
    
    <h2>Il Nostro Team:</h2>
    <div class="team-grid">
        {% for membro in team %}
            <div class="team-member">
                <h3>{{ membro.nome }}</h3>
                <p>{{ membro.ruolo }}</p>
                <p>{{ membro.descrizione }}</p>
            </div>
        {% endfor %}
    </div>
{% endblock %}

🎯 Vantaggi dell'Ereditarietà

DRY (Don't Repeat Yourself)
Non ripetere header/footer in ogni file
Manutenzione Facile
Cambi il menu in UN SOLO file (base.html)
Consistenza
Tutte le pagine hanno lo stesso layout
Sviluppo Rapido
Nuove pagine in pochi minuti

🔧 Comandi Avanzati nei Template

Comando Scopo Esempio
{% include "header.html" %} Includi un template dentro un altro Per riutilizzare componenti specifici
{{ super() }} Mantieni il contenuto del blocco padre {% block title %}{{ super() }} - Pagina{% endblock %}
{% block nome %}{% endblock %} Definisci un blocco personalizzato Per script specifici o metatag

💪 Esercizi Pratici

Esercizio 1
Facile

📝 Template per una Lista della Spesa

Crea una pagina che mostra una lista della spesa con:

  • Un titolo "La Mia Lista della Spesa"
  • Una lista non ordinata con 5 prodotti
  • Accanto a ogni prodotto, mostra la quantità
  • Usa un ciclo for e passalo da Python
💡 Suggerimento - app.py
lista_spesa = [
    {"prodotto": "Pane", "quantita": 2},
    {"prodotto": "Latte", "quantita": 1},
    # ... aggiungi altri 3 prodotti
]

Esercizio 2
Medio

📊 Tabella Studenti con Condizioni

Crea una pagina che mostra una tabella di studenti con:

  • Nome, Cognome, Voto, Stato (Promosso/Bocciato)
  • Se voto ≥ 18 → Stato = "✅ Promosso" (verde)
  • Se voto < 18 → Stato = "❌ Bocciato" (rosso)
  • Calcola la media dei voti alla fine
💡 Suggerimento - Jinja2
<tr class="{% if studente.voto >= 18 %}promosso{% else %}bocciato{% endif %}">

Esercizio 3
Difficile

🏗️ Sito Completo con Template Base

Crea un piccolo sito con 3 pagine:

  1. Home - Presentazione del sito
  2. Prodotti - Tabella di prodotti (nome, prezzo, categoria)
  3. Contatti - Form fittizio di contatto

Requisiti:

  • Usa un template base con header e footer
  • Il menu deve mostrare la pagina corrente in grassetto
  • Ogni pagina deve avere un titolo diverso nel browser tab
  • Usa almeno un filtro Jinja2 in ogni pagina

🔐 Validazione Dati nei Form

Quando gli utenti compilano form, è fondamentale validare i dati prima di usarli. Ecco come fare con Flask:

1
Template con Form di Login

📄 templates/login.html
<!DOCTYPE html>
<html lang="it">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
    <h1>🔐 Accedi al Sito</h1>
    
    <!-- Mostra messaggi di errore -->
    {% if errore %}
        <div style="background: #fee2e2; color: #991b1b; padding: 15px; border-radius: 8px; margin-bottom: 20px;">
            ❌ {{ errore }}
        </div>
    {% endif %}
    
    <!-- Form di login -->
    <form method="POST" action="/login">
        <div style="margin-bottom: 15px;">
            <label for="username">Username:</label><br>
            <input type="text" id="username" name="username" style="width: 300px; padding: 8px;" required>
        </div>
        
        <div style="margin-bottom: 15px;">
            <label for="password">Password:</label><br>
            <input type="password" id="password" name="password" style="width: 300px; padding: 8px;" required>
        </div>
        
        <button type="submit" style="background: #4f46e5; color: white; padding: 10px 20px; border: none; border-radius: 6px;">
            Accedi
        </button>
    </form>
    
    <p style="margin-top: 20px;">
        Non hai un account? <a href="/registrazione">Registrati qui</a>
    </p>
</body>
</html>

2
Route Flask con Validazione

📄 app.py
from flask import Flask, render_template, request, session, redirect, url_for

app = Flask(__name__)
app.secret_key = 'tua_chiave_segreta'  # ⚠️ IMPORTANTE per le sessioni!

# Utenti di esempio (in un'app reale sarebbe un database)
utenti = {
    'admin': 'password123',
    'mario': 'mario2024',
    'lucia': 'luciaSecure'
}

@app.route('/')
def home():
    # Controlla se l'utente è loggato
    if 'username' in session:
        return f'''
        <h1>Benvenuto {session['username']}!</h1>
        <p>Sei correttamente loggato nel sistema.</p>
        <a href="/dashboard">Vai alla Dashboard</a> | 
        <a href="/logout">Logout</a>
        '''
    return '''
    <h1>Benvenuto Ospite</h1>
    <p>Per accedere alle funzionalità del sito:</p>
    <a href="/login">Login</a> | 
    <a href="/registrazione">Registrati</a>
    '''

@app.route('/login', methods=['GET', 'POST'])
def login():
    # Se l'utente è già loggato, reindirizza alla home
    if 'username' in session:
        return redirect('/')
    
    if request.method == 'POST':
        # 1. Prendi i dati dal form
        username = request.form.get('username', '').strip()
        password = request.form.get('password', '').strip()
        
        # 2. VALIDAZIONE BASE
        errori = []
        
        # Controllo campi vuoti
        if not username:
            errori.append("Inserisci l'username")
        if not password:
            errori.append("Inserisci la password")
        
        # Controllo credenziali (se i campi non sono vuoti)
        if username and password:
            # Verifica se l'utente esiste
            if username not in utenti:
                errori.append("Username non trovato")
            # Verifica se la password è corretta
            elif utenti[username] != password:
                errori.append("Password errata")
        
        # 3. Se ci sono errori, mostra il form con errori
        if errori:
            return render_template('login.html', errore=" | ".join(errori))
        
        # 4. Se tutto OK, salva in sessione e reindirizza
        session['username'] = username
        session['logged_in'] = True
        
        return redirect('/dashboard')
    
    # Se è una GET, mostra il form vuoto
    return render_template('login.html')

@app.route('/dashboard')
def dashboard():
    # 🔒 CONTROLLO ACCESSO: solo utenti loggati
    if 'username' not in session:
        return redirect('/login')
    
    username = session['username']
    return f'''
    <!DOCTYPE html>
    <html lang="it">
    <head>
        <meta charset="UTF-8">
        <title>Dashboard</title>
    </head>
    <body>
        <h1>👋 Benvenuto nella Dashboard, {username}!</h1>
        <h3>🔐 Area Riservata</h3>
        <p>Questa pagina è accessibile solo agli utenti autenticati.</p>
        
        <div style="background: #f0f9ff; padding: 20px; border-radius: 8px; margin: 20px 0;">
            <h4>💡 I tuoi dati di sessione:</h4>
            <ul>
                <li>Username: <strong>{username}</strong></li>
                <li>Stato: ✅ Loggato</li>
                <li>Session ID: {session.get('_id', 'N/A')}</li>
            </ul>
        </div>
        
        <a href="/">🏠 Home</a> | 
        <a href="/logout">🚪 Logout</a>
    </body>
    </html>
    '''

@app.route('/logout')
def logout():
    # Cancella la sessione
    session.clear()
    return '''
    <h1>Logout effettuato</h1>
    <p>Sei stato disconnesso correttamente.</p>
    <a href="/">Torna alla Home</a>
    '''

if __name__ == '__main__':
    app.run(debug=True)

💡 Come Funziona il Sistema di Validazione

1. Recupero Dati

request.form.get('campo') prende i dati inviati dal form

2. Pulizia Dati

.strip() rimuove spazi all'inizio e alla fine

3. Validazione

Controlla se i campi sono vuoti o non validi

4. Feedback

Mostra errori specifici all'utente se ci sono problemi

🔒 Controllo Accesso con Sessioni

Per proteggere le pagine riservate (come /dashboard), usa questo pattern:

@app.route('/pagina-riservata')
def pagina_riservata():
    # Controlla se l'utente è loggato
    if 'username' not in session:
        # Se non è loggato, reindirizza al login
        return redirect('/login')
    
    # Se è loggato, mostra la pagina
    return render_template('pagina_riservata.html')

⚠️ IMPORTANTE: Senza app.secret_key le sessioni non funzionano! La secret key cripta i dati della sessione.

🎯 Esempio Pratico di Validazione Avanzata

📄 Validazione Form di Registrazione
@app.route('/registrazione', methods=['GET', 'POST'])
def registrazione():
    if request.method == 'POST':
        username = request.form.get('username', '').strip()
        email = request.form.get('email', '').strip()
        password = request.form.get('password', '').strip()
        conferma = request.form.get('conferma_password', '').strip()
        
        errori = []
        
        # Validazione Username
        if len(username) < 3:
            errori.append("L'username deve essere di almeno 3 caratteri")
        elif not username.isalnum():
            errori.append("L'username può contenere solo lettere e numeri")
        
        # Validazione Email
        if '@' not in email or '.' not in email:
            errori.append("Email non valida")
        
        # Validazione Password
        if len(password) < 6:
            errori.append("La password deve essere di almeno 6 caratteri")
        elif password != conferma:
            errori.append("Le password non coincidono")
        
        if errori:
            return render_template('registrazione.html', errori=errori)
        
        # Se tutto OK, registra l'utente
        # (qui salveresti nel database)
        session['username'] = username
        return redirect('/dashboard')
    
    return render_template('registrazione.html')

📝 Template per Mostrare Errori di Validazione

📄 templates/registrazione.html - Parte errori
<!-- Se ci sono errori, mostrali -->
{% if errori %}
    <div style="background: #fee2e2; padding: 15px; border-radius: 8px; margin-bottom: 20px;">
        <h4 style="color: #991b1b; margin-top: 0;">❌ Si sono verificati errori:</h4>
        <ul style="margin-bottom: 0;">
            {% for errore in errori %}
                <li>{{ errore }}</li>
            {% endfor %}
        </ul>
    </div>
{% endif %}

⚠️ Errori Comuni e Soluzioni

❌ TemplateNotFound

Errore: jinja2.exceptions.TemplateNotFound: index.html

Causa: Flask non trova il template nella cartella templates/

Soluzione:

  • Verifica che la cartella si chiami ESATTAMENTE templates
  • Deve essere allo stesso livello di app.py
  • Controlla i permessi di lettura della cartella

❌ UndefinedError

Errore: jinja2.exceptions.UndefinedError: 'variabile' is undefined

Causa: Stai usando una variabile nel template che non hai passato da Python

Soluzione:

  • Controlla l'ortografia della variabile
  • Verifica di averla passata in render_template()
  • Usa {{ variabile|default('Valore di default') }}

❌ TemplateSyntaxError

Errore: jinja2.exceptions.TemplateSyntaxError: expected token 'end of statement block'

Causa: Dimenticato {% endblock %} o {% endfor %}

Soluzione:

  • Assicurati che ogni {% block %} abbia il suo {% endblock %}
  • Ogni {% for %} deve avere {% endfor %}
  • Ogni {% if %} deve avere {% endif %}

📋 Riepilogo Concetti Chiave

📁

Struttura

  • Cartella templates/ obbligatoria
  • File .html dentro templates/
  • render_template('file.html')
🔧

Jinja2 Sintassi

  • {{ variabile }} → Stampa
  • {% for %} → Ciclo
  • {% if %} → Condizione
  • |filtro → Modifica variabile
🏗️

Template Inheritance

  • {% extends "base.html" %}
  • {% block nome %}{% endblock %}
  • DRY: Don't Repeat Yourself
  • Layout consistente
🚀

Best Practices

  • Separa logica da presentazione
  • Usa sempre template base
  • Nomi file chiari e descrittivi
  • Organizza templates in sottocartelle

✅ Modulo 3 Completato!

Ora sai creare pagine HTML professionali con Flask e Jinja2. Pronto per il prossimo passo?

ORA SEI QUI
📄 Modulo 3
Templates

MODULO 4

🎯 Cosa Aspettarti nel Prossimo Modulo

🎨

CSS e Stili

Rendi i tuoi templates bellissimi

🖼️

Immagini e Media

Aggiungi foto e icone al tuo sito

📦

Cartella Static

Organizza file CSS, JS, immagini

Torna in alto