🛣️ Modulo 2: Route e URL Dinamici
Impara a creare percorsi flessibili e gestire parametri negli URL
2 di 8
45 minuti
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:
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)
Sostituisci il contenuto del tuo app.py con il codice sopra e avvia il server.
Ora puoi visitare:
http://localhost:5000/→ Homepagehttp://localhost:5000/about→ Chi Siamohttp://localhost:5000/contatti→ Contattihttp://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 |
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>
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)
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> |
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)
/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 ✅
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!
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:
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)
/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:
- Definire due route separate: una con e una senza parametro
- Oppure usare
defaults: specifica il valore di default nella route - Oppure usare query parameters: per parametri veramente opzionali
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!
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)
# 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)
- 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:
- Homepage (
/,/home,/negozio) – mostra “Benvenuto nel Negozio Online” - Prodotto (
/prodotto/<int:id>) – mostra “Prodotto numero {id}” - Categoria (
/categoria/<nome>) – mostra “Categoria: {nome}” - Carrello (
/carrello/,/carrello/<utente>) – con default ‘Ospite’, mostra “Carrello di {utente}” - 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:
- Homepage (3 route diverse:
/,/home,/biblioteca) - Libro per ID (
/libro/<int:id>) – mostra “Libro #ID” - Libro completo (
/libro/<int:anno>/<autore>/<titolo>)- anno: anno di pubblicazione
- autore: nome autore
- titolo: titolo del libro
- Studente (
/studente/,/studente/<nome>) – default ‘Visitatore’ - Prestiti (
/prestiti/<nome>) – mostra “Prestiti di {nome}” - 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:
- Homepage (3 route:
/,/home,/ricette) - Ricetta per ID (
/ricetta/<int:id>) - Ricetta dettagliata (
/ricetta/<categoria>/<difficolta>/<slug>)- categoria: primi, secondi, dolci, antipasti
- difficolta: facile, media, difficile
- slug: nome-ricetta (es: pasta-carbonara)
- Chef (
/chef/,/chef/<nome>) – default ‘Chef Sconosciuto’ - Ingrediente (
/ingrediente/<nome>) – mostra ricette con quell’ingrediente - 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())
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 |
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
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
- 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:
- 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
- Articolo singolo (
/articolo/<int:id>)- Mostra titolo e contenuto dell’articolo
- Link all’autore e alla categoria
- Link “Torna alla home”
- Articolo con dettagli (
/articolo/<int:anno>/<int:mese>/<slug>)- Mostra articolo con anno, mese e slug
- Validazione automatica con convertitori
- Categoria (
/categoria/<nome>)- Mostra articoli della categoria
- Link agli articoli
- Autore (
/autore/,/autore/<nome>)- Default: ‘Autore Sconosciuto’
- Mostra info autore e suoi articoli
- Cerca (
/cerca/)- Query parameter:
?q=...&categoria=... - Entrambi opzionali
- Mostra risultati ricerca
- Query parameter:
- Commenti (
/articolo/<int:id>/commenti, methods=[‘GET’, ‘POST’])- GET: mostra form commenti
- POST: ricevi e mostra il commento inviato
- 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
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! 🎉