Custom Validation

  • Implement custom validation logic in Django Forms to ensure data integrity and proper error handling.
  • What is Custom Validation?

    Custom validation allows us to apply our own business rules to form fields or models beyond Django’s built-in validation.

    Example:

    • Age must be 18+

    • Username must not contain numbers

    • Email domain must be specific (e.g., gmail.com)

    Types of Validation in Django

    Type

    Where Used

    Built-in

    Automatically by Django

    Field-level

    Single field

    Form-level

    Multiple fields together

    Custom validators

    Reusable validation functions

    What is a Custom Validator?

    A custom validator is a function or class that raises ValidationError if data is invalid.

Simple Custom Validator Function [ validators.py ]

This validator checks minimum age.

from django.core.exceptions import ValidationError

def validate_age(value):
    if value < 18:
        raise ValidationError("Age must be 18 or above")
  • Using Custom Validator in Model

Apply Custom Validator to Model Field [ models.py ]

from django.db import models
from .validators import validate_age

class Student(models.Model):
    name = models.CharField(max_length=100)
    age = models.IntegerField(validators=[validate_age])
  • Validator runs automatically during form validation.

    Using Custom Validator in Form

Apply Custom Validator in Form Field

forms.py

from django import forms
from .validators import validate_age

class StudentForm(forms.Form):
    age = forms.IntegerField(validators=[validate_age])
  • Field-Level Custom Validation

clean_fieldname() Method [ forms.py ]

Validates one specific field inside a form.

class StudentForm(forms.ModelForm):
    class Meta:
        model = Student
        fields = ['name', 'email', 'age']

    def clean_name(self):
        name = self.cleaned_data.get('name')
        if name.isdigit():
            raise forms.ValidationError("Name cannot be numeric")
        return name
  • Method name must be clean_<fieldname>.

    Form-Level Custom Validation

clean() Method

Validates multiple fields together.

def clean(self):
        cleaned_data = super().clean()
        email = cleaned_data.get('email')
        age = cleaned_data.get('age')

        if email and age and age < 21 and email.endswith('@company.com'):
            raise forms.ValidationError(
                "Company email allowed only for age 21+"
            )
  • Error Handling in Django Forms

    What is ValidationError?

    ValidationError is raised when invalid data is detected.

    from django.core.exceptions import ValidationError


Handling Errors in View [ views.py ]

Checks form validity and re-renders form with errors.

def student_view(request):
    form = StudentForm(request.POST or None)
    if form.is_valid():
        form.save()
    return render(request, 'student.html', {'form': form})

  • Django automatically attaches errors to the form.

    Display Errors in Template

Show Validation Errors

student.html

<form method="post">
    {% csrf_token %}

    {{ form.non_field_errors }}

    <div>
        {{ form.name.label }}<br>
        {{ form.name }}
        {{ form.name.errors }}
    </div>

    <div>
        {{ form.age.label }}<br>
        {{ form.age }}
        {{ form.age.errors }}
    </div>

    <button type="submit">Submit</button>
</form>
  • Common Validation Errors & Solutions

    Error

    Cause

    Solution

    ValidationError not raised

    Wrong method name

    Use clean_<field>

    Error not showing

    Template issue

    Render form.errors

    Data not saving

    Form invalid

    Check errors

Registration Form with Multiple Validations

class RegistrationForm(forms.ModelForm):
    class Meta:
        model = Student
        fields = ['name', 'email', 'age']

    def clean_email(self):
        email = self.cleaned_data.get('email')
        if not email.endswith('@gmail.com'):
            raise forms.ValidationError("Only Gmail emails allowed")
        return email

    def clean(self):
        cleaned_data = super().clean()
        age = cleaned_data.get('age')
        if age and age < 18:
            raise forms.ValidationError("Registration allowed for 18+ only")