🛣️ Modulo 2: Route e URL Dinamici

Impara a creare percorsi flessibili e gestire parametri negli URL

📚

MODULO
2 di 8

⏱️

TEMPO
45 minuti

🎯

LIVELLO
Base

🎯 Cosa sono le Route?

Le route (o percorsi) sono gli “indirizzi” della tua applicazione web. Ogni route corrisponde a un URL specifico e determina quale funzione Python viene eseguita.

🗺️ Le Route come una Mappa Stradale

Immagina la tua applicazione web come una città:

  • / è la piazza principale (homepage)
  • /about è via About, dove trovi informazioni
  • /contatti è via Contatti, dove lasci un messaggio
  • /prodotti è la zona commerciale

Flask fa da “navigatore GPS”: quando riceve un URL, sa esattamente quale funzione eseguire!

📌 Route Statiche

Le route statiche sono URL fissi e predefiniti. Vediamo come crearne diverse:

📄 app.py – Multiple Route
from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return 'Homepage - Benvenuto!'

@app.route('/about')
def about():
    return 'Pagina Chi Siamo'

@app.route('/contatti')
def contatti():
    return 'Pagina Contatti'

@app.route('/servizi')
def servizi():
    return 'I Nostri Servizi'

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

1
Prova il codice

Sostituisci il contenuto del tuo app.py con il codice sopra e avvia il server.

Ora puoi visitare:

  • http://localhost:5000/ → Homepage
  • http://localhost:5000/about → Chi Siamo
  • http://localhost:5000/contatti → Contatti
  • http://localhost:5000/servizi → Servizi

💡 Regole per le Route

  • Ogni route deve iniziare con /
  • I nomi delle funzioni devono essere univoci
  • Le route sono case-sensitive: /About ≠ /about
  • Puoi usare - e _ negli URL

⚠️ Il Trailing Slash (Slash Finale)

Una delle cose più importanti da capire nelle route Flask è la differenza tra URL con e senza slash finale.

Route Definita URL Richiesto Risultato
@app.route('/about/') /about Redirect automatico a /about/
@app.route('/about/') /about/ Funziona correttamente
@app.route('/about') /about Funziona correttamente
@app.route('/about') /about/ Errore 404 Not Found
📝 Convenzione Consigliata:

Usa sempre il trailing slash (/about/) per le route che rappresentano “sezioni” del sito. Flask si comporterà come le cartelle di un file system, accettando sia /about che /about/.

🎨 Route Dinamiche con Parametri

Le route dinamiche ti permettono di catturare parti dell’URL e usarle come variabili nella tua funzione. Questo è fondamentale per creare applicazioni scalabili!

🤔 Perché servono?

Immagina un sito con profili utente. Invece di creare manualmente:

  • /utente/mario
  • /utente/luigi
  • /utente/paolo
  • … e così via per migliaia di utenti!

Crei UNA SOLA route dinamica che gestisce TUTTI i profili: /utente/<nome>

📄 app.py – Route Dinamiche Base
from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return 'Homepage'

@app.route('/utente/<nome>')
def profilo(nome):
    return f'Profilo di {nome}'

@app.route('/saluta/<nome>')
def saluta(nome):
    return f'Ciao {nome}, benvenuto!'

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

1
Prova gli URL dinamici

Sostituisci il codice e prova a visitare:

  • http://localhost:5000/utente/mario → “Profilo di mario”
  • http://localhost:5000/utente/anna → “Profilo di anna”
  • http://localhost:5000/saluta/carlo → “Ciao carlo, benvenuto!”

Puoi inserire QUALSIASI nome nell’URL!

🔍 Sintassi dei Parametri

<nome_variabile> nell’URL diventa un parametro della funzione.

@app.route('/post/<titolo>')
def mostra_post(titolo):  ← Il nome deve corrispondere!
    return f'Stai leggendo: {titolo}'

🔢 Convertitori di Tipo

Flask permette di specificare il tipo del parametro URL. Questo ti protegge da input errati e converte automaticamente il valore.

Convertitore Accetta Esempio Route
string Testo (default) <string:nome>
int Numeri interi positivi <int:id>
float Numeri decimali <float:prezzo>
path Testo con slash / <path:percorso>
uuid UUID validi <uuid:id>
📄 app.py – Convertitori in Azione
from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return 'Homepage'

@app.route('/prodotto/<int:id>')
def prodotto(id):
    return f'Stai visualizzando il prodotto #{id}'

@app.route('/prezzo/<float:valore>')
def prezzo(valore):
    iva = valore * 1.22
    return f'Prezzo: €{valore:.2f} - Con IVA: €{iva:.2f}'

@app.route('/articolo/<int:anno>/<int:mese>/<slug>')
def articolo(anno, mese, slug):
    return f'Articolo: {slug} (pubblicato il {mese}/{anno})'

@app.route('/file/<path:percorso>')
def file(percorso):
    return f'Percorso file: {percorso}'

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

1
Prova i convertitori

  • /prodotto/123 → Funziona
  • /prodotto/abc → Errore 404 (non è un int)
  • /prezzo/19.99 → Calcola IVA
  • /articolo/2024/12/guida-flask → Multipli parametri
  • /file/documenti/2024/report.pdf → Path completo

🛡️ Protezione Automatica

Quando usi <int:id>, Flask accetta SOLO numeri interi. Se l’utente prova a inserire testo, riceve automaticamente un errore 404. Non devi controllare manualmente il tipo!

🔗 Route Multiple per una Funzione

A volte vuoi che la stessa funzione risponda a URL diversi. Flask lo rende semplicissimo!

📄 app.py – Route Multiple
from flask import Flask

app = Flask(__name__)

@app.route('/')
@app.route('/home')
@app.route('/index')
def home():
    return 'Benvenuto nella Homepage!'

@app.route('/info')
@app.route('/about')
@app.route('/chi-siamo')
def about():
    return 'Informazioni su di noi'

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

Ora questi URL portano tutti alla stessa pagina:

  • / → Homepage
  • /home → Homepage
  • /index → Homepage

💡 Quando usare Route Multiple?

  • Compatibilità: mantenere vecchi URL funzionanti
  • Convenienza: permettere diverse varianti dello stesso URL
  • Internazionalizzazione: /about e /chi-siamo per diverse lingue

Parametri Opzionali

Per creare parametri opzionali nelle route Flask, devi usare uno di questi metodi:

📄 app.py – Metodi per Parametri Opzionali
from flask import Flask, request

app = Flask(__name__)

# METODO 1: Due route separate (Consigliato)
@app.route('/saluta/')
def saluta_senza_nome():
    return 'Ciao Ospite!'

@app.route('/saluta/<nome>')
def saluta_con_nome(nome):
    return f'Ciao {nome}!'

# METODO 2: Usando defaults
@app.route('/benvenuto/', defaults={'nome': 'Amico'})
@app.route('/benvenuto/<nome>')
def benvenuto(nome):
    return f'Benvenuto {nome}!'

# METODO 3: Query parameters
@app.route('/ciao/')
def ciao():
    nome = request.args.get('nome', 'Visitatore')
    return f'Ciao {nome}!'

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

1
Comportamento

  • /saluta/ → “Ciao Ospite!” (usa la prima funzione)
  • /saluta/Mario → “Ciao Mario!” (usa la seconda funzione)
  • /benvenuto/ → “Benvenuto Amico!” (usa default ‘Amico’)
  • /benvenuto/Luigi → “Benvenuto Luigi!”
  • /ciao/ → “Ciao Visitatore!”
  • /ciao/?nome=Paolo → “Ciao Paolo!”

🎯 Regola Importante

I parametri nelle route Flask (<nome>) sono sempre obbligatori nell’URL. Per renderli opzionali devi:

  1. Definire due route separate: una con e una senza parametro
  2. Oppure usare defaults: specifica il valore di default nella route
  3. Oppure usare query parameters: per parametri veramente opzionali
📝 Esempio Avanzato

Per gestire profili utente con parametri opzionali:

@app.route('/profilo/', defaults={'username': 'ospite', 'pagina': 1})
@app.route('/profilo/<username>', defaults={'pagina': 1})
@app.route('/profilo/<username>/<int:pagina>')
def profilo(username, pagina):
    if username == 'ospite':
        return 'Profilo ospite - Registrati!'
    else:
        return f'Profilo di {username} - Pagina {pagina}'

🔗 url_for() – Generare URL Dinamici

Flask fornisce url_for() per generare URL basati sul nome delle funzioni. Questo è molto più sicuro che scrivere URL manualmente!

🤔 Perché usare url_for()?

Problema: Se scrivi /utente/123 hardcoded nel codice e poi cambi la route in /profilo/123, devi cercare e cambiare TUTTI gli URL nel progetto.

Soluzione: Con url_for('profilo', id=123), Flask genera automaticamente l’URL corretto, qualunque sia la route definita!

Confronto: url_for() vs URL Hardcoded

CON URL HARDCODED (NON FARE COSÌ)

Problemi:

  • Se cambio la route, devo cercare tutti i link
  • Facile sbagliare la scrittura dell’URL
  • Non gestisce caratteri speciali
  • Difficile mantenere
@app.route('/utente/<nome>')
def profilo(nome):
    return f'Profilo di {nome}'

# In un'altra funzione:
return '<a href="/utente/mario">Profilo Mario</a>'

Se cambio la route in /profilo/nome, questo link si rompe!

CON URL_FOR() (CORRETTO)

Vantaggi:

  • Se cambio la route, i link si aggiornano automaticamente
  • Nessun errore di battitura possibile
  • Gestisce automaticamente caratteri speciali
  • Facile da mantenere
@app.route('/utente/<nome>')
def profilo(nome):
    return f'Profilo di {nome}'

# In un'altra funzione:
return f'<a href="{url_for("profilo", nome="mario")}">Profilo Mario</a>'

Posso cambiare la route in /profilo/nome senza toccare questo link!

📄 app.py – url_for() in Azione
from flask import Flask, url_for

app = Flask(__name__)

@app.route('/')
def home():
    # Genera URL per altre pagine
    about_url = url_for('about')
    user_url = url_for('profilo', nome='mario')
    
    return f'''
    <h1>Homepage</h1>
    <p>Vai a <a href="{about_url}">Chi Siamo</a></p>
    <p>Vai a <a href="{user_url}">Profilo Mario</a></p>
    '''

@app.route('/about')
def about():
    return 'Pagina Chi Siamo'

@app.route('/utente/<nome>')
def profilo(nome):
    return f'Profilo di {nome}'

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

Esempi Avanzati di url_for()

# URL statici semplici
url_for('home')                    # → /

# URL con parametri dinamici
url_for('profilo', nome='mario')   # → /utente/mario
url_for('articolo', id=123)        # → /articolo/123

# URL con più parametri
url_for('articolo_dettaglio', anno=2024, mese=12, slug='flask-guida')
# → /articolo/2024/12/flask-guida

# URL con query string
url_for('profilo', nome='mario', pagina=2, ordina='data')
# → /utente/mario?pagina=2&ordina=data

# URL assoluti (con dominio completo)
url_for('home', _external=True)
# → http://localhost:5000/

# URL con ancoraggio
url_for('home', _anchor='sezione2')
# → /#sezione2

# URL con parametri speciali (codifica automatica)
url_for('cerca', q='caffè & biscotti')
# → /cerca?q=caff%C3%A8+%26+biscotti

Esempio Reale: Sistema di Navigazione

from flask import Flask, url_for

app = Flask(__name__)

@app.route('/')
def home():
    # Genera dinamicamente tutti i link del sito
    menu_items = [
        {'nome': 'Home', 'endpoint': 'home'},
        {'nome': 'Chi Siamo', 'endpoint': 'about'},
        {'nome': 'Prodotti', 'endpoint': 'prodotti_lista'},
        {'nome': 'Contatti', 'endpoint': 'contatti'},
    ]
    
    # Genera il menu dinamicamente
    menu_html = '<nav><ul>'
    for item in menu_items:
        url = url_for(item['endpoint'])
        menu_html += f'<li><a href="{url}">{item["nome"]}</a></li>'
    menu_html += '</ul></nav>'
    
    return f'''
    <!DOCTYPE html>
    <html>
    <head><title>Il Mio Sito</title></head>
    <body>
        {menu_html}
        <h1>Benvenuto!</h1>
        <p>Questo menu è generato dinamicamente con url_for()</p>
    </body>
    </html>
    '''

@app.route('/about')
def about():
    return 'Pagina Chi Siamo'

@app.route('/prodotti')
def prodotti_lista():
    return 'Lista Prodotti'

@app.route('/contatti')
def contatti():
    return 'Pagina Contatti'

# Se un giorno cambio le route, NON devo toccare il menu!
# Basta cambiare i decoratori qui sopra

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

✨ Vantaggi di url_for():

  • Manutenibilità: cambi la route in un solo punto
  • Sicurezza: gestisce automaticamente caratteri speciali
  • Consistenza: gli URL sono sempre corretti
  • Deploy: funziona anche se l’app è in una sottocartella
  • Internazionalizzazione: facile gestire URL multilingua

💪 Esercizi Pratici di Consolidamento

Prima di passare ai metodi HTTP, mettiamo in pratica quanto appreso finora con questi esercizi progressivi:

🎯 ESERCIZIO 1 – Negozio Online (Livello Base)

Crea un’applicazione Flask per un negozio online con i seguenti endpoint:

📋 Requisiti:

  1. Homepage (/, /home, /negozio) – mostra “Benvenuto nel Negozio Online”
  2. Prodotto (/prodotto/<int:id>) – mostra “Prodotto numero {id}”
  3. Categoria (/categoria/<nome>) – mostra “Categoria: {nome}”
  4. Carrello (/carrello/, /carrello/<utente>) – con default ‘Ospite’, mostra “Carrello di {utente}”
  5. Ricerca (/ricerca/) – usa query parameter ?articolo=... con default ‘tutti’

🎯 Obiettivo:

Nella homepage, usa url_for() per collegare almeno 3 prodotti, 2 categorie e il carrello.

✅ Concetti da applicare:

  • Route multiple per lo stesso endpoint
  • Parametri dinamici con <int:id> e <nome>
  • Parametri opzionali con defaults
  • Query parameters con request.args.get()
  • Generazione URL con url_for()

🎯 ESERCIZIO 2 – Biblioteca Scolastica (Livello Intermedio)

Crea un sistema per gestire una biblioteca:

📋 Requisiti:

  1. Homepage (3 route diverse: /, /home, /biblioteca)
  2. Libro per ID (/libro/<int:id>) – mostra “Libro #ID”
  3. Libro completo (/libro/<int:anno>/<autore>/<titolo>)
    • anno: anno di pubblicazione
    • autore: nome autore
    • titolo: titolo del libro
  4. Studente (/studente/, /studente/<nome>) – default ‘Visitatore’
  5. Prestiti (/prestiti/<nome>) – mostra “Prestiti di {nome}”
  6. Ricerca (/ricerca/) – con query ?titolo=...&autore=... (entrambi opzionali)

🎯 Obiettivo:

Dalla homepage, collega con url_for():

  • Almeno 3 libri diversi usando tutte le tipologie di route
  • 2 profili studente
  • Una ricerca di esempio

✅ Concetti da applicare:

  • Parametri multipli nell’URL
  • Mix di tipi: <int:anno> e <autore>
  • Defaults avanzati
  • Query parameters multipli
  • url_for() con parametri complessi

🎯 ESERCIZIO 3 – Ricettario (Livello Avanzato)

Crea un’applicazione completa per ricette di cucina:

📋 Requisiti:

  1. Homepage (3 route: /, /home, /ricette)
  2. Ricetta per ID (/ricetta/<int:id>)
  3. Ricetta dettagliata (/ricetta/<categoria>/<difficolta>/<slug>)
    • categoria: primi, secondi, dolci, antipasti
    • difficolta: facile, media, difficile
    • slug: nome-ricetta (es: pasta-carbonara)
  4. Chef (/chef/, /chef/<nome>) – default ‘Chef Sconosciuto’
  5. Ingrediente (/ingrediente/<nome>) – mostra ricette con quell’ingrediente
  6. Filtro ricerca (/filtro/) – query ?categoria=...&tempo=...&persone=... (tutti opzionali)

🎯 Obiettivo:

Crea una homepage professionale con:

  • Menu di navigazione con url_for()
  • Link a 3 ricette usando TUTTE le tipologie di route
  • Sezione “Ricette per ingrediente” (almeno 2)
  • Form di ricerca con filtri
  • Profili chef (almeno 2)

💡 Suggerimento:

Crea un dizionario con alcune ricette di esempio per rendere l’app più realistica:

ricette = {
    1: {'nome': 'Carbonara', 'categoria': 'primi', 'difficolta': 'media'},
    2: {'nome': 'Tiramisù', 'categoria': 'dolci', 'difficolta': 'facile'},
    3: {'nome': 'Ossobuco', 'categoria': 'secondi', 'difficolta': 'difficile'}
}

✅ Concetti da applicare:

  • Tutti i tipi di parametri URL
  • Struttura complessa con più parametri
  • Query parameters multipli
  • url_for() in situazioni reali
  • Organizzazione codice professionale

✅ Criteri di Valutazione

Per considerare l’esercizio completato con successo, verifica che:

  • ✅ Tutti gli endpoint funzionano correttamente
  • ✅ Uso corretto di url_for() nella homepage
  • ✅ Parametri URL gestiti correttamente (int, string, ecc.)
  • ✅ Default values implementati dove richiesti
  • ✅ Query parameters con valori di default funzionanti
  • ✅ Codice pulito e ben commentato
  • ✅ Le route multiple funzionano tutte
  • ✅ Nessun URL hardcoded (solo url_for())

💡 Esempio Struttura per Esercizio 1:

from flask import Flask, url_for, request

app = Flask(__name__)

@app.route('/')
@app.route('/home')
@app.route('/negozio')
def home():
    # Usa url_for() per tutti i link
    prod1_url = url_for('prodotto', id=1)
    prod2_url = url_for('prodotto', id=2)
    cat_elettronica = url_for('categoria', nome='elettronica')
    carrello_url = url_for('carrello')
    ricerca_url = url_for('ricerca', articolo='smartphone')
    
    return f'''
    <h1>Benvenuto nel Negozio Online</h1>
    
    <h2>Prodotti in Evidenza</h2>
    <ul>
        <li><a href="{prod1_url}">Prodotto 1</a></li>
        <li><a href="{prod2_url}">Prodotto 2</a></li>
    </ul>
    
    <h2>Categorie</h2>
    <ul>
        <li><a href="{cat_elettronica}">Elettronica</a></li>
    </ul>
    
    <p><a href="{carrello_url}">Vai al Carrello</a></p>
    <p><a href="{ricerca_url}">Cerca: smartphone</a></p>
    '''

@app.route('/prodotto/<int:id>')
def prodotto(id):
    return f'Prodotto numero {id}'

# Aggiungi qui le altre route...

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

📬 Metodi HTTP nelle Route

Di default, le route Flask accettano solo richieste GET. Ma puoi specificare altri metodi HTTP:

Metodo Scopo Quando usarlo
GET Ottenere dati Visualizzare pagine, leggere info
POST Inviare dati Form di registrazione, upload file
PUT Aggiornare tutto Sostituire completamente una risorsa
PATCH Aggiornare parzialmente Modificare solo alcuni campi
DELETE Eliminare Cancellare una risorsa
📄 app.py – Metodi HTTP
from flask import Flask, request

app = Flask(__name__)

@app.route('/dati', methods=['GET'])
def mostra_dati():
    return 'Qui visualizzi i dati (GET)'

@app.route('/invia', methods=['POST'])
def invia_dati():
    return 'Dati ricevuti! (POST)'

@app.route('/modifica', methods=['GET', 'POST'])
def modifica():
    if request.method == 'POST':
        return 'Sto elaborando i dati inviati'
    else:
        return 'Mostra il form di modifica'

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

Differenze Chiave tra GET e POST

METODO GET

Caratteristiche:

  • Dati nella URL (visibili)
  • Limitato a circa 2000 caratteri
  • Può essere cacheato
  • Può essere bookmarkato
  • Sicurezza: bassa
  • Uso: per leggere dati
http://sito.com/login?user=mario&pass=123

METODO POST

Caratteristiche:

  • Dati nel body (nascosti)
  • Nessun limite di dimensione
  • Non viene cacheato
  • Non può essere bookmarkato
  • Sicurezza: media/alta
  • Uso: per inviare dati
POST /login HTTP/1.1
Host: sito.com
Content-Type: application/x-www-form-urlencoded

user=mario&pass=123

Esempio Completo: Sistema Login con GET e POST

from flask import Flask, request, redirect, url_for

app = Flask(__name__)

# Database fittizio di utenti
utenti = {
    'mario': 'password123',
    'luigi': 'super456',
    'admin': 'admin123'
}

@app.route('/')
def home():
    return '''
    <h1>Login System</h1>
    <form method="POST" action="''' + url_for('login') + '''">
        Username: <input name="username"><br>
        Password: <input type="password" name="password"><br>
        <button type="submit">Login (POST)</button>
    </form>
    <hr>
    <a href="''' + url_for('login') + '?username=mario&password=password123' + '''">
        Login automatico Mario (GET - NON SICURO!)
    </a>
    '''

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        # Dati dal form POST (sicuro)
        username = request.form.get('username', '').lower()
        password = request.form.get('password', '')
    else:
        # Dati dalla query string GET (non sicuro)
        username = request.args.get('username', '').lower()
        password = request.args.get('password', '')
    
    # Verifica credenziali
    if username in utenti and utenti[username] == password:
        return f'''
        <h1>Accesso Consentito!</h1>
        <p>Benvenuto {username}</p>
        <p><a href="/">Torna alla home</a></p>
        '''
    else:
        return f'''
        <h1>Accesso Negato!</h1>
        <p>Credenziali errate per {username}</p>
        <p><a href="/">Riprova</a></p>
        '''

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

🔍 Come Controllare il Metodo

Usa request.method per sapere quale metodo HTTP è stato usato:

if request.method == 'POST':
    # Elabora i dati inviati
    username = request.form.get('username')
elif request.method == 'GET':
    # Mostra il form
    # O recupera parametri dalla query string
    search = request.args.get('q')

Metodo Dati Sicurezza Cache Bookmark
GET Nella URL (visibili) 🔴 Bassa Si può cacheare Può essere bookmarkato
POST Nel body (nascosti) 🟡 Media Non si cachea Non può essere bookmarkato
PUT Nel body 🟢 Alta Non si cachea Non può essere bookmarkato
DELETE 🟢 Alta Non si cachea Non può essere bookmarkato

📝 Riepilogo Modulo 2

✅ Cosa Hai Imparato:

  • Creare route statiche multiple
  • Usare route dinamiche con parametri
  • Convertitori di tipo (int, float, path, ecc.)
  • Route multiple per la stessa funzione
  • Parametri opzionali con valori di default
  • Specificare metodi HTTP (GET, POST, ecc.)
  • Generare URL con url_for()
  • Il significato del trailing slash
  • Differenze tra GET e POST
  • Vantaggi di url_for() vs URL hardcoded
  • Esempi pratici di sistemi login
  • Gestione avanzata dei parametri

Best Practices Apprese

  • Usa sempre url_for() invece di URL hardcoded
  • GET per leggere dati, POST per inviarli
  • Trailing slash per le “sezioni” del sito
  • Convertitori di tipo per validazione automatica
  • Route multiple per compatibilità
  • Parametri opzionali con valori di default

🎯 Nel Prossimo Modulo

Imparerai a creare vere pagine HTML usando i Templates Jinja2! Dirai addio alle stringhe HTML nel codice Python e creerai un’interfaccia professionale.

🏆 Esercizio Finale Completo

🎯 Progetto Completo: Mini Blog Professionale

Metti insieme TUTTO quello che hai imparato in questo modulo creando un mini blog completo e funzionante!

📋 Requisiti Obbligatori:

  1. Homepage (/, /home, /blog)
    • Mostra titolo del blog
    • Menu di navigazione con url_for()
    • Lista di 3-5 articoli con link
    • Sezione categorie
    • Form di ricerca
  2. Articolo singolo (/articolo/<int:id>)
    • Mostra titolo e contenuto dell’articolo
    • Link all’autore e alla categoria
    • Link “Torna alla home”
  3. Articolo con dettagli (/articolo/<int:anno>/<int:mese>/<slug>)
    • Mostra articolo con anno, mese e slug
    • Validazione automatica con convertitori
  4. Categoria (/categoria/<nome>)
    • Mostra articoli della categoria
    • Link agli articoli
  5. Autore (/autore/, /autore/<nome>)
    • Default: ‘Autore Sconosciuto’
    • Mostra info autore e suoi articoli
  6. Cerca (/cerca/)
    • Query parameter: ?q=...&categoria=...
    • Entrambi opzionali
    • Mostra risultati ricerca
  7. Commenti (/articolo/<int:id>/commenti, methods=[‘GET’, ‘POST’])
    • GET: mostra form commenti
    • POST: ricevi e mostra il commento inviato
  8. About (/about, /chi-siamo, /info)
    • Informazioni sul blog

💾 Database Simulato (copia questo nel tuo codice):

# Database articoli
ARTICOLI = {
    1: {
        'titolo': 'Introduzione a Python',
        'slug': 'introduzione-python',
        'autore': 'Mario',
        'categoria': 'Programmazione',
        'anno': 2024,
        'mese': 1,
        'contenuto': 'Python è un linguaggio fantastico...'
    },
    2: {
        'titolo': 'Flask per principianti',
        'slug': 'flask-principianti',
        'autore': 'Luigi',
        'categoria': 'Web Development',
        'anno': 2024,
        'mese': 3,
        'contenuto': 'Flask è un micro-framework...'
    },
    3: {
        'titolo': 'Route dinamiche in Flask',
        'slug': 'route-dinamiche-flask',
        'autore': 'Mario',
        'categoria': 'Web Development',
        'anno': 2024,
        'mese': 6,
        'contenuto': 'Le route dinamiche permettono...'
    }
}

# Database autori
AUTORI = {
    'mario': {
        'nome_completo': 'Mario Rossi',
        'bio': 'Sviluppatore Python con 5 anni di esperienza',
        'articoli': [1, 3]
    },
    'luigi': {
        'nome_completo': 'Luigi Verdi',
        'bio': 'Esperto di Web Development',
        'articoli': [2]
    }
}

# Database categorie
CATEGORIE = {
    'Programmazione': [1],
    'Web Development': [2, 3]
}

✅ Checklist Completamento:

  • ✅ Tutte le 8 route implementate e funzionanti
  • ✅ Nessun URL hardcoded (solo url_for())
  • ✅ Homepage con menu completo
  • ✅ Convertitori di tipo usati correttamente
  • ✅ Almeno una route con GET e POST
  • ✅ Query parameters gestiti
  • ✅ Defaults implementati
  • ✅ Route multiple dove appropriato
  • ✅ Codice ben commentato
  • ✅ Gestione errori (articolo non trovato, ecc.)

🌟 Bonus (opzionali ma consigliati):

  • Aggiungi stile CSS inline per rendere il blog più carino
  • Implementa un sistema di “articoli correlati”
  • Aggiungi paginazione agli articoli
  • Crea una sezione “Articoli più letti”
  • Implementa un form di contatto con POST

💡 Esempio Struttura Iniziale:

from flask import Flask, request, url_for

app = Flask(__name__)

# [INSERISCI QUI I DATABASE ARTICOLI, AUTORI, CATEGORIE]

@app.route('/')
@app.route('/home')
@app.route('/blog')
def home():
    # Genera menu
    about_url = url_for('about')
    
    # Genera lista articoli
    html = '<h1>Il Mio Blog</h1>'
    html += f'<nav><a href="{about_url}">Chi Siamo</a></nav>'
    html += '<h2>Articoli Recenti</h2><ul>'
    
    for id, articolo in ARTICOLI.items():
        art_url = url_for('articolo', id=id)
        html += f'<li><a href="{art_url}">{articolo["titolo"]}</a></li>'
    
    html += '</ul>'
    return html

@app.route('/articolo/<int:id>')
def articolo(id):
    if id not in ARTICOLI:
        return '<h1>Articolo non trovato</h1><a href="/">Torna alla home</a>', 404
    
    art = ARTICOLI[id]
    autore_url = url_for('autore', nome=art['autore'].lower())
    cat_url = url_for('categoria', nome=art['categoria'])
    home_url = url_for('home')
    
    return f'''
    <h1>{art["titolo"]}</h1>
    <p>Autore: <a href="{autore_url}">{art["autore"]}</a></p>
    <p>Categoria: <a href="{cat_url}">{art["categoria"]}</a></p>
    <p>{art["contenuto"]}</p>
    <p><a href="{home_url}">← Torna alla home</a></p>
    '''

# [CONTINUA CON LE ALTRE ROUTE...]

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

🎯 Obiettivo Finale

Al termine di questo esercizio dovresti avere un’applicazione Flask completamente funzionante che dimostra la tua padronanza di:

  • Route statiche e dinamiche
  • Convertitori di tipo
  • Parametri opzionali e defaults
  • url_for() per generazione URL
  • Metodi HTTP GET e POST
  • Query parameters
  • Organizzazione codice pulita

Congratulazioni se arrivi a completarlo! Sei pronto per il Modulo 3 sui Templates! 🎉

Torna in alto