Form
I form sono un elemento fondamentale di qualsiasi applicazione web. Django fornisce un sistema robusto per definire form, validare i dati e renderizzarli nei template in modo sicuro e flessibile.
Definire un Form
Un form in Django si definisce creando una classe che eredita da forms.Form:
# forms.py
from django import forms
class ContattoForm(forms.Form):
nome = forms.CharField(max_length=100, label="Il tuo nome")
email = forms.EmailField(label="La tua email")
messaggio = forms.CharField(widget=forms.Textarea, label="Messaggio")
priorita = forms.ChoiceField(choices=[
('bassa', 'Bassa'),
('media', 'Media'),
('alta', 'Alta'),
])
Tipi di Campi Comuni
Django offre numerosi tipi di campi per i form:
class EsempioForm(forms.Form):
testo = forms.CharField(max_length=200)
numero = forms.IntegerField(min_value=0)
decimale = forms.DecimalField(max_digits=5, decimal_places=2)
email = forms.EmailField()
url = forms.URLField()
data = forms.DateField()
booleano = forms.BooleanField(required=False)
scelta = forms.ChoiceField(choices=[('a', 'Opzione A'), ('b', 'Opzione B')])
file = forms.FileField(required=False)
Gestire il Form nella View
La logica tipica per gestire un form nella view prevede di distinguere tra richieste GET e POST:
# views.py
from django.shortcuts import render, redirect
from .forms import ContattoForm
def contatto(request):
if request.method == 'POST':
form = ContattoForm(request.POST)
if form.is_valid():
nome = form.cleaned_data['nome']
email = form.cleaned_data['email']
messaggio = form.cleaned_data['messaggio']
# Elabora i dati (es. invia email, salva nel db)
return redirect('successo')
else:
form = ContattoForm()
return render(request, 'contatto.html', {'form': form})
Il metodo is_valid() esegue la validazione di tutti i campi. Se la validazione ha successo, i dati puliti sono disponibili in form.cleaned_data.
Rendering del Form nei Template
Django offre diversi metodi per renderizzare un form nel template:
# Rendering automatico completo
# <form method="post">
# {% csrf_token %}
# {{ form.as_p }}
# <button type="submit">Invia</button>
# </form>
I metodi di rendering disponibili sono:
form.as_pâ ogni campo racchiuso in un tag<p>form.as_tableâ ogni campo in una riga di tabella<tr>form.as_ulâ ogni campo in un elemento di lista<li>form.as_divâ ogni campo in un<div>(introdotto in Django 5.x)
Rendering Manuale
Per un controllo completo sul markup, puoi renderizzare ogni campo manualmente:
# <form method="post">
# {% csrf_token %}
# <div class="campo">
# <label for="{{ form.nome.id_for_label }}">Nome:</label>
# {{ form.nome }}
# {% if form.nome.errors %}
# <span class="errore">{{ form.nome.errors.0 }}</span>
# {% endif %}
# </div>
# <div class="campo">
# <label for="{{ form.email.id_for_label }}">Email:</label>
# {{ form.email }}
# </div>
# <button type="submit">Invia</button>
# </form>
Gestione degli Errori
Quando la validazione fallisce, gli errori sono accessibili tramite form.errors:
# views.py
def contatto(request):
if request.method == 'POST':
form = ContattoForm(request.POST)
if form.is_valid():
# processa i dati
return redirect('successo')
else:
# form.errors contiene tutti gli errori
# form.errors e' un dizionario: {'campo': ['messaggio errore']}
print(form.errors)
else:
form = ContattoForm()
return render(request, 'contatto.html', {'form': form})
Nel template puoi mostrare gli errori globali del form:
# {% if form.non_field_errors %}
# <div class="errori-globali">
# {% for errore in form.non_field_errors %}
# <p>{{ errore }}</p>
# {% endfor %}
# </div>
# {% endif %}
Valori Iniziali
Puoi precompilare un form passando valori iniziali:
def contatto(request):
form = ContattoForm(initial={
'nome': 'Mario Rossi',
'email': 'mario@esempio.it',
})
return render(request, 'contatto.html', {'form': form})
Conclusione
I form di Django offrono un sistema completo per la raccolta e validazione dei dati utente. Dalla definizione dei campi al rendering nei template, ogni aspetto e gestito in modo sicuro e strutturato. Per form collegati ai modelli del database, Django mette a disposizione i ModelForm, che vedremo nel prossimo capitolo.