Form Validation with clean()

A snippet showing how to validate form fields with clean().


# forms.py

from django import forms

class RegistrationForm(forms.Form):
    username = forms.CharField(max_length=50)
    email = forms.EmailField()
    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_password = cleaned_data.get("confirm_password")

        if password and confirm_password and password != confirm_password:
            raise forms.ValidationError("Passwords do not match!")

        return cleaned_data
  

# views.py

from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import RegistrationForm

def register(request):
    if request.method == "POST":
        form = RegistrationForm(request.POST)
        if form.is_valid():
            # Save user or perform logic
            messages.success(request, "Registration successful!")
            return redirect("register")
    else:
        form = RegistrationForm()
    return render(request, "register.html", {"form": form})
  

# templates/register.html

<div class="row justify-content-center">
  <div class="col-md-8 col-lg-6">
    <form method="post" class="bg-white border rounded p-3">
      {% csrf_token %}
      <h5 class="mb-3">Register</h5>

      {{ form.as_p }}

      {% if form.errors %}
        <div class="alert alert-danger">Please fix the errors below.</div>
      {% endif %}

      <button type="submit" class="btn btn-primary w-100">Register</button>
    </form>
  </div>
</div>
  
Explanation:
  • Override clean() for cross-field validation and add custom logic.
  • Always call super().clean() to preserve built-in validations.
  • Raise forms.ValidationError with a helpful message for users.
  • Category Forms & Validation
  • Total Views 1093
  • Last Modified 21 September, 2025
  • Tags #forms #validation #clean #input
Never miss a story on Django.wiki

Subscribe for fresh tutorials, snippets, and updates.

By subscribing you agree to our Privacy Policy.