Метод clean

Метод clean применяется к классу формы и позволяет выполнять валидацию данных, которые требуют проверки связи между несколькими полями или сложной логики. Метод вызывается автоматически в процессе валидации формы после выполнения стандартных валидаторов полей и метода clean_<fieldname> для каждого поля. В методе clean можно получить доступ к уже очищенным данным из словаря cleaned_data и вернуть этот же словарь после проверки. Если данные не проходят валидацию, метод должен выбрасывать исключение ValidationError.

Синтаксис

pythonfrom django import forms
from django.core.exceptions import ValidationError

class MyForm(forms.Form):
  # поля формы
  
  def clean(self):
    cleaned_data = super().clean()
    # валидация данных
    return cleaned_data

Пример

Создадим форму регистрации, где необходимо проверить, что пароль и подтверждение пароля совпадают:

pythonfrom django import forms
from django.core.exceptions import ValidationError

class RegistrationForm(forms.Form):
  username = forms.CharField(max_length=100)
  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 ValidationError('Passwords do not match')
    
    return cleaned_data

Пример

Рассмотрим валидацию формы, где нужно проверить, что возраст пользователя находится в допустимом диапазоне в зависимости от его роли:

pythonfrom django import forms
from django.core.exceptions import ValidationError

class UserForm(forms.Form):
  name = forms.CharField(max_length=100)
  age = forms.IntegerField(min_value=0, max_value=120)
  role = forms.ChoiceField(choices=[
    ('student', 'Student'),
    ('teacher', 'Teacher'),
    ('admin', 'Administrator')
  ])

  def clean(self):
    cleaned_data = super().clean()
    age = cleaned_data.get('age')
    role = cleaned_data.get('role')
    
    if role == 'student' and age < 6:
      raise ValidationError('Student must be at least 6 years old')
    
    if role == 'teacher' and age < 18:
      raise ValidationError('Teacher must be at least 18 years old')
    
    if role == 'admin' and age < 21:
      raise ValidationError('Administrator must be at least 21 years old')
    
    return cleaned_data

Пример использования формы с обработкой ошибок:

pythonfrom django.shortcuts import render
from .forms import UserForm

def create_user(request):
  if request.method == 'POST':
    form = UserForm(request.POST)
    if form.is_valid():
      # обработка данных
      return render(request, 'success.html')
  else:
    form = UserForm()
  return render(request, 'user_form.html', {'form': form})

Пример

Валидация с использованием нескольких полей для проверки даты: начало события не может быть позже его окончания:

pythonfrom django import forms
from django.core.exceptions import ValidationError
from datetime import date

class EventForm(forms.Form):
  name = forms.CharField(max_length=200)
  start_date = forms.DateField()
  end_date = forms.DateField()

  def clean(self):
    cleaned_data = super().clean()
    start_date = cleaned_data.get('start_date')
    end_date = cleaned_data.get('end_date')
    
    if start_date and end_date and start_date > end_date:
      raise ValidationError('Start date cannot be later than end date')
    
    return cleaned_data

Вывод формы в шаблоне:

html<form method="post">
  {% csrf_token %}
  {{ form.as_p }}
  <button type="submit">Create event</button>
</form>

Результат валидации при неправильных данных:

python"Form errors: {'__all__': ['Start date cannot be later than end date']}"

Смотрите также

  • метод is_valid,
    который запускает валидацию формы
  • атрибут cleaned_data,
    который содержит очищенные данные формы
  • атрибут errors,
    который содержит ошибки валидации
  • метод add_error,
    который добавляет ошибки к конкретным полям