Redirect e Errori HTTP
La gestione corretta dei redirect e degli errori HTTP è fondamentale per offrire una buona esperienza utente e per mantenere una navigazione coerente. Django fornisce strumenti integrati per gestire reindirizzamenti, errori 404, 500 e altre situazioni comuni.
Redirect con redirect()
La funzione redirect() è lo shortcut piu utilizzato per reindirizzare lâutente a unâaltra pagina:
from django.shortcuts import redirect
def crea_articolo(request):
if request.method == 'POST':
# Salva l'articolo...
articolo = Articolo.objects.create(
titolo=request.POST['titolo'],
contenuto=request.POST['contenuto'],
)
# Redirect usando il nome della URL
return redirect('blog:dettaglio', slug=articolo.slug)
return render(request, 'blog/crea.html')
redirect() accetta diversi tipi di argomento:
# Redirect a una URL con nome
return redirect('blog:lista')
# Redirect a un URL assoluto
return redirect('/blog/')
# Redirect a un URL esterno
return redirect('https://www.esempio.com')
# Redirect a un oggetto con get_absolute_url()
return redirect(articolo)
# Redirect permanente (301)
return redirect('blog:lista', permanent=True)
HttpResponseRedirect
Per un controllo piu fine, usa HttpResponseRedirect direttamente:
from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect
from django.urls import reverse
def vecchia_pagina(request):
# Redirect temporaneo (302)
return HttpResponseRedirect(reverse('blog:lista'))
def url_cambiato(request):
# Redirect permanente (301) - usato quando una URL cambia definitivamente
return HttpResponsePermanentRedirect(reverse('nuova-pagina'))
La differenza tra redirect temporaneo (302) e permanente (301) e importante per la SEO: il redirect 301 indica ai motori di ricerca di aggiornare i propri indici.
Errore 404: Pagina Non Trovata
Sollevare Http404
Per indicare che una risorsa non esiste, solleva lâeccezione Http404:
from django.http import Http404
def dettaglio_articolo(request, slug):
try:
articolo = Articolo.objects.get(slug=slug)
except Articolo.DoesNotExist:
raise Http404("Articolo non trovato")
return render(request, 'blog/dettaglio.html', {'articolo': articolo})
Lo Shortcut get_object_or_404()
get_object_or_404() semplifica il pattern sopra in una sola riga:
from django.shortcuts import get_object_or_404
def dettaglio_articolo(request, slug):
articolo = get_object_or_404(Articolo, slug=slug)
return render(request, 'blog/dettaglio.html', {'articolo': articolo})
Funziona anche con queryset filtrati:
# Con filtri aggiuntivi
articolo = get_object_or_404(Articolo, slug=slug, pubblicato=True)
# Con un queryset personalizzato
articoli_pubblicati = Articolo.objects.filter(pubblicato=True)
articolo = get_object_or_404(articoli_pubblicati, slug=slug)
Esiste anche get_list_or_404() per le liste:
from django.shortcuts import get_list_or_404
def per_categoria(request, categoria):
articoli = get_list_or_404(Articolo, categoria__slug=categoria)
return render(request, 'blog/lista.html', {'articoli': articoli})
Risposte di Errore HTTP
Django fornisce classi specifiche per i diversi codici di errore:
from django.http import (
HttpResponseBadRequest, # 400
HttpResponseForbidden, # 403
HttpResponseNotFound, # 404
HttpResponseNotAllowed, # 405
HttpResponseServerError, # 500
)
def vista_protetta(request):
if not request.user.has_perm('blog.modifica'):
return HttpResponseForbidden("Non hai i permessi per questa azione.")
# Logica della view...
def solo_post(request):
if request.method != 'POST':
return HttpResponseNotAllowed(['POST'])
# Elabora la richiesta POST...
Handler Personalizzati per gli Errori
Django permette di personalizzare le pagine di errore definendo handler nel file urls.py principale del progetto:
# miosito/urls.py
handler400 = 'miosito.views.errore_400'
handler403 = 'miosito.views.errore_403'
handler404 = 'miosito.views.errore_404'
handler500 = 'miosito.views.errore_500'
# miosito/views.py
from django.shortcuts import render
def errore_400(request, exception):
return render(request, 'errori/400.html', status=400)
def errore_403(request, exception):
return render(request, 'errori/403.html', status=403)
def errore_404(request, exception):
return render(request, 'errori/404.html', status=404)
def errore_500(request):
# Nota: handler500 non riceve il parametro exception
return render(request, 'errori/500.html', status=500)
Le pagine di errore personalizzate sono visibili solo quando DEBUG = False. In modalita di sviluppo, Django mostra le sue pagine di debug dettagliate.
Template per le Pagine di Errore
Crea template dedicati nella cartella templates/errori/:
<!-- templates/errori/404.html -->
<!DOCTYPE html>
<html>
<head><title>Pagina non trovata</title></head>
<body>
<h1>404 - Pagina non trovata</h1>
<p>La pagina che stai cercando non esiste.</p>
<a href="{% url 'home' %}">Torna alla home</a>
</body>
</html>
Conclusione
Django offre un sistema completo per gestire redirect e errori HTTP. Lo shortcut redirect() semplifica i reindirizzamenti, get_object_or_404() elimina codice ripetitivo per la gestione degli oggetti inesistenti, e gli handler personalizzati permettono di creare pagine di errore professionali e coerenti con il design del sito.