Custom Validators Example

A snippet showing how to implement custom validators for Django forms.


# validators.py

from django.core.exceptions import ValidationError
import re

USERNAME_RE = re.compile(r"^[a-z0-9_]+$")

def validate_username(value: str):
    """Allow only lowercase letters, digits, and underscores."""
    if not USERNAME_RE.match(value):
        raise ValidationError("Username may contain lowercase letters, digits, and underscores only.")

def validate_file_size(file_obj, max_mb=5):
    """Limit upload size in megabytes (default 5 MB)."""
    limit = max_mb * 1024 * 1024
    if file_obj.size > limit:
        raise ValidationError(f"File too large. Max size is {max_mb} MB.")
  

# forms.py

from django import forms
from .validators import validate_username, validate_file_size

class ProfileForm(forms.Form):
    username = forms.CharField(
        max_length=30,
        validators=[validate_username],
        help_text="Lowercase letters, digits, underscores",
    )
    avatar = forms.FileField(required=False)

    def clean_avatar(self):
        f = self.cleaned_data.get("avatar")
        if f:
            validate_file_size(f, max_mb=2)
        return f
  

# models.py (optional reuse on model fields)

from django.db import models
from .validators import validate_username

class Profile(models.Model):
    username = models.CharField(max_length=30, unique=True, validators=[validate_username])
    # avatar FileField/ImageField can be validated in forms or with a custom field validator
  
Explanation:
  • Validators are callables that raise ValidationError when input is invalid.
  • Attach validators via the field's validators=[...] argument or in clean_FIELD.
  • Reuse the same validator for both form fields and model fields to ensure consistency.
  • Category Forms & Validation
  • Total Views 1082
  • Last Modified 01 September, 2025
  • Tags #forms #validation #custom #fields
Previous snippet
Field-Specific Validation
Next snippet
File Upload with Forms
Never miss a story on Django.wiki

Subscribe for fresh tutorials, snippets, and updates.

By subscribing you agree to our Privacy Policy.