← Back to Django Course | Chapter 7: Django Forms | Lesson 10 of 11

Custom Form Validation

Custom validation is you teaching the form a special rule the built-in checks don't already know, like 'the password must contain a number.'

Validating a Single Field

A method named clean_<fieldname> runs automatically during is_valid() and must return the field's cleaned value.

Example: Validating a Single Field

A method named clean_<fieldname> runs automatically during is_valid() and must return the field's cleaned value.

markup
from django.core.exceptions import ValidationError


class SignupForm(forms.Form):
    username = forms.CharField(max_length=50)

    def clean_username(self):
        username = self.cleaned_data['username']
        if ' ' in username:
            raise ValidationError('Username cannot contain spaces.')
        return username
{# Django-only code -- models.py/views.py/urls.py/settings.py snippets, or template markup using Django template tags/variables -- can't run standalone via Judge0 or the browser preview, since it needs a real Django project. Only this course's pure-Python examples (example_lang == 'python', no Django imports) are actually runnable, so those still get the button below. #}

Validating Across Multiple Fields

Overriding clean() lets you compare two fields, like confirming a password matches its confirmation field.

Example: Validating Across Multiple Fields

Overriding clean() lets you compare two fields, like confirming a password matches its confirmation field.

markup
def clean(self):
    cleaned_data = super().clean()
    password = cleaned_data.get('password')
    confirm = cleaned_data.get('confirm_password')
    if password and confirm and password != confirm:
        raise ValidationError('Passwords do not match.')
    return cleaned_data
{# Django-only code -- models.py/views.py/urls.py/settings.py snippets, or template markup using Django template tags/variables -- can't run standalone via Judge0 or the browser preview, since it needs a real Django project. Only this course's pure-Python examples (example_lang == 'python', no Django imports) are actually runnable, so those still get the button below. #}

Showing the Custom Error

A raised ValidationError is automatically attached to that field's errors and displayed by {{ form.as_p }}.

Example: Showing the Custom Error

A raised ValidationError is automatically attached to that field's errors and displayed by {{ form.as_p }}.

markup
<form method="post">
  {% csrf_token %}
  {{ form.as_p }}
  <button type="submit">Sign Up</button>
</form>
{# Django-only code -- models.py/views.py/urls.py/settings.py snippets, or template markup using Django template tags/variables -- can't run standalone via Judge0 or the browser preview, since it needs a real Django project. Only this course's pure-Python examples (example_lang == 'python', no Django imports) are actually runnable, so those still get the button below. #}
Common Mistakes
  1. Naming a clean method wrong (e.g. clean_Email instead of clean_email) so Django never calls it.
  2. Forgetting to return the cleaned value at the end of a clean_<field> method, silently wiping that field's data.
  3. Raising a plain Exception instead of django.core.exceptions.ValidationError, which Django can't attach to the form's errors.
Chapter Summary
  • A clean_<fieldname> method validates one specific field and must return the cleaned value.
  • Overriding clean() (no field name) validates relationships between multiple fields at once.
  • Raise django.core.exceptions.ValidationError to reject a value with a custom error message.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.