Validazione nei form
L'interfaccia dei form di Django offre diversi metodi per validare i dati inseriti in un form. Il primo metodo è quello di usare un validatore specifico su un singolo campo. Ipotizziamo di voler creare un form per implementare una ricerca e di voler validare che la query contenga un numero minimo di caratteri. Il nostro codice potrebbe assomigliare al seguente:
from django import forms
from django.core.exceptions import ValidationError
def almeno_tre_caratteri(value):
if len(value) < 3:
raise ValidationError("La query deve essere di almeno 3 caratteri")
class RicercaForm(forms.Form):
query = forms.CharField(validators=[almeno_tre_caratteri])
Abbiamo creato un Form
con un singolo campo query
che viene validato dalla funzione
almeno_tre_caratteri
che in caso il valore non abbiamo sia lungo almeno 3 caratteri alza l'eccezione
ValidationError
con un messaggio di errore. Come possiamo notare il validatore non è altro che una
semplice funzione che prende il valore del campo come parametro.
Per verificare che il nostro form ed il nostro validatore funzionino a dovere dobbiamo scrivere dei test come i seguenti:
from corsi.forms import RicercaForm, almeno_tre_caratteri
class RicercaFormTestCase(TestCase):
def test_validatore_alza_eccezione_con_meno_di_3_caratteri(self):
with self.assertRaisesMessage(ValidationError, "La query deve essere di almeno 3 caratteri"):
almeno_tre_caratteri("ab")
def test_validatore_non_alza_eccezione_con_almeno_3_caratteri(self):
self.assertIsNone(almeno_tre_caratteri("abc"))
def test_form_valida_campo_query(self):
form = RicercaForm({"query": "abc"})
self.assertTrue(form.is_valid())
def test_form_restituisce_errore_con_query_minore_di_3_caratteri(self):
form = RicercaForm({"query": "ab"})
self.assertFalse(form.is_valid())
def test_form_restituisce_errore_senza_dati(self):
form = RicercaForm({})
self.assertFalse(form.is_valid())
In questi stiamo testando che il validatore validi correttamente la stringa passata e in caso di
errore restituisca il messaggio che ci aspettiamo. Validiamo invece che il form applichi il validatore
e cambi il valore restituito dal metodo is_valid()
.
Django offre altri due metodo per validare un form: il metodo clean()
del form e i metodi
clean_<nomecampo>()
per validare ogni singolo campo. A differenza del sistema col validatore questi
metodi permettono di cambiare il contenuto del campo che stanno controllando.
Possiamo reimplementare il form precedente validando il singolo campo in questo modo:
class RicercaForm(forms.Form):
query = forms.CharField()
def clean_query(self):
query = self.cleaned_data["query"]
if len(query) < 3:
raise ValidationError("La query deve essere di almeno 3 caratteri")
return query
Possiamo notare che ora dobbiamo sempre restituire qualcosa che verrà salvato nella chiave query
di cleaned_data
al termine della validazione.
A differenza del metodo clean
per il singolo campo, quello generico del form ha visione su tutti i
campi del form e quindi è possibile validare un campo in relazione agli altri.
class RicercaForm(forms.Form):
query = forms.CharField()
def clean(self):
super().clean()
query = self.cleaned_data.get("query", "")
if len(query) < 3:
raise ValidationError("La query deve essere di almeno 3 caratteri")
Qui dobbiamo fare attenzione ad una cosa importante. A differenza dei due metodi precedenti in questo
caso non possiamo dare per scontato che i campi dei form siano valorizzati. Infatti stiamo usando la
stringa vuota ""
come default nel caso che il campo query
non sia definito. Per il metodo clean
non è obbligatorio restituire il valore di cleaned_data
se non abbiamo cambiato il contenuto da quello
che ha settato la chiamata al metodo clean()
di default.
Esercizi
Leggi la documentazione sui validatori e quale validatore avremmo potuto usare al posto di implementarne una nostra versione.
Leggi la documentazione ufficiale sulla validazione dei form.