Field-Level Validation
You can validate individual fields by defining clean_ methods on your form.
from django import forms
class RegistrationForm(forms.Form):
username = forms.CharField(max_length=150)
age = forms.IntegerField()
def clean_age(self):
age = self.cleaned_data.get('age')
if age < 18:
raise forms.ValidationError('You must be at least 18 years old.')
return age
The method name must match clean_ followed by the field name. Always return the cleaned value.
Using ValidationError
The ValidationError class lets you raise errors with custom messages during validation.
from django.core.exceptions import ValidationError
def validate_even(value):
if value % 2 != 0:
raise ValidationError('Only even numbers are allowed.')
class NumberForm(forms.Form):
number = forms.IntegerField(validators=[validate_even])
You can pass ValidationError to the validators argument of any form field for reusable validation logic.
Custom Validators
Custom validators are reusable functions that check a single value and raise ValidationError if invalid.
from django.core.validators import RegexValidator
phone_validator = RegexValidator(
regex=r'^\+?1?\d{9,15}$',
message='Enter a valid phone number.'
)
class ContactForm(forms.Form):
phone = forms.CharField(validators=[phone_validator])
Custom validators can be shared across multiple forms. They run before the field's built-in validation.
Try it Yourself →Form-Level Validation with clean()
The clean() method validates the entire form after individual fields are cleaned.
class OrderForm(forms.Form):
product = forms.CharField()
quantity = forms.IntegerField()
discount_code = forms.CharField(required=False)
def clean(self):
cleaned_data = super().clean()
product = cleaned_data.get('product')
quantity = cleaned_data.get('quantity')
if product == 'premium' and quantity > 10:
raise forms.ValidationError('Premium products limited to 10 per order.')
return cleaned_data
Use clean() when validation depends on multiple fields. Always call super().clean() and return the cleaned data.
Collecting Multiple Errors
You can collect multiple validation errors and display them all at once.
class MultiErrorForm(forms.Form):
password = forms.CharField(widget=forms.PasswordInput)
confirm_password = forms.CharField(widget=forms.PasswordInput)
def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get('password')
confirm = cleaned_data.get('confirm_password')
errors = []
if password and confirm and password != confirm:
errors.append(forms.ValidationError('Passwords do not match.'))
if password and len(password) < 8:
errors.append(forms.ValidationError('Password must be at least 8 characters.'))
if errors:
raise forms.ValidationError(errors)
return cleaned_data
Passing a list of ValidationError instances lets you report all problems at once instead of stopping at the first error.