python 42 lines · 1 tab

Django model validation with clean method

Priya Sharma Jan 2026
1 tab
from django.db import models
from django.core.exceptions import ValidationError
from django.utils import timezone


class Event(models.Model):
    name = models.CharField(max_length=200)
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()
    capacity = models.IntegerField()
    registered_count = models.IntegerField(default=0)

    def clean(self):
        # Validate time range
        if self.start_time and self.end_time:
            if self.end_time <= self.start_time:
                raise ValidationError({
                    'end_time': 'End time must be after start time.'
                })

            if self.start_time < timezone.now():
                raise ValidationError({
                    'start_time': 'Cannot create event in the past.'
                })

        # Validate capacity
        if self.capacity and self.registered_count:
            if self.registered_count > self.capacity:
                raise ValidationError(
                    'Registered count cannot exceed capacity.'
                )

        # Business rule validation
        duration = (self.end_time - self.start_time).total_seconds() / 3600
        if duration > 12:
                raise ValidationError(
                    'Events cannot be longer than 12 hours.'
                )

    def save(self, *args, **kwargs):
        self.full_clean()  # Run validation
        super().save(*args, **kwargs)
1 file · python Explain with highlit

The clean() method validates model instances before saving. I raise ValidationError for invalid data. This runs on form submission and can be called explicitly with full_clean(). I validate cross-field constraints that can't be expressed as field validators. Unlike field-level validation, clean() has access to all fields. I use NON_FIELD_ERRORS for general validation errors. For complex validation, I sometimes split into multiple methods. This ensures data integrity at the model layer.


Related snips

Share this code

Here's the card — post it anywhere.

Django model validation with clean method — share card
Link copied