Методи is_valid() та clean() — це центральні елементи механізму, що забезпечує правильність обробки даних форми. Але на відміну від шестерень, які просто обертаються, ці методи дозволяють вам додати логіку перевірки даних, яка підходить саме для вашого проєкту.
is_valid()
Метод is_valid() викликається для перевірки коректності даних, надісланих користувачем. Він автоматично викликає валідацію кожного окремого поля форми, перевіряючи значення на відповідність встановленим правилам, зазначеним у визначенні полів (наприклад, required, max_length і т. д.).
Якщо всі перевірки проходять успішно, то метод повертає True. Інакше він наповнює об'єкт form.errors списком помилок і повертає False.
Приклад виклику:
if form.is_valid():
# Якщо дані форми коректні, обробляємо їх
print(form.cleaned_data)
else:
# Виводимо помилки
print(form.errors)
clean()
Ось тут починається справжня магія! Метод clean() викликається після того, як спрацювали валідації полів, але перед поверненням значення is_valid(). Цей метод дозволяє обробити дані одразу всіх полів форми, а також додати додаткові перевірки, які неможливо (або незручно) зробити на рівні валідаторів окремих полів.
Кастомізація методу clean(): навіщо і як?
Уявіть: ви розробляєте форму реєстрації, і потрібно перевірити не лише коректність окремого поля (наприклад, довжину пароля), а й зв'язок між полями, наприклад, щоб пароль і його підтвердження збігалися. Метод clean() — саме те місце, де проводиться ця перевірка.
Для кастомізації логіки валідації перевизначте метод clean() у вашому класі форми. Ось приклад форми реєстрації, де перевіряється збіг паролів:
from django import forms
class RegistrationForm(forms.Form):
username = forms.CharField(max_length=150, required=True)
email = forms.EmailField(required=True)
password = forms.CharField(widget=forms.PasswordInput, required=True)
confirm_password = forms.CharField(widget=forms.PasswordInput, required=True)
def clean(self):
# Викликаємо базову реалізацію clean(), щоб отримати очищені дані полів
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("Паролі не збігаються!")
return cleaned_data
- Отримання очищених даних: метод
super().clean()повертає словник із даними, що пройшли попередню перевірку. - Логіка перевірки: використовуємо стандартну логіку Python для перевірки умов.
- Генерація помилок: якщо помилку знайдено, викликаємо
forms.ValidationErrorіз повідомленням про помилку. - Повернення даних: якщо перевірка завершилася успішно, поверніть оновлені
cleaned_data.
А що з окремими полями? Метод clean_<fieldname>()
Іноді тобі потрібно валідовувати окреме поле, але стандартних валідаторів недостатньо. У таких випадках ти можеш перевизначити метод clean_<fieldname>().
Наведемо приклад перевірки унікальності імені користувача.
Припустимо, у нас є список імен, які не можна використовувати (наприклад, "admin" або "root"). Ось як це можна реалізувати:
class CustomForm(forms.Form):
username = forms.CharField(max_length=150, required=True)
def clean_username(self):
username = self.cleaned_data.get("username")
prohibited_usernames = ["admin", "root", "superuser"]
if username.lower() in prohibited_usernames:
raise forms.ValidationError("Це ім'я користувача заборонено.")
# Завжди повертай перевірене значення
return username
- Метод
clean_<fieldname>(): цей метод автоматично викликається для перевірки конкретного поля. - Отримання даних: значення поля доступне через
self.cleaned_data. - Валідація та помилки: якщо дані не відповідають вимогам, ти викликаєш
ValidationError.
Розширена обробка даних
Іноді ви не тільки валідируєте дані, але й хочете перетворити їх перед збереженням. Наприклад, можна автоматично приводити імена до нижнього регістру:
class LowerCaseUsernameForm(forms.Form):
username = forms.CharField(max_length=150, required=True)
def clean_username(self):
username = self.cleaned_data.get("username")
if not username.isalnum():
raise forms.ValidationError("Ім'я користувача повинно містити тільки літери та цифри.")
# Перетворюємо ім'я до нижнього регістру
return username.lower()
Тепер, навіть якщо користувач ввів USER123, форма збереже його як user123.
Перевизначення методу is_valid()
Хоча метод clean() використовується частіше, іноді виникає необхідність втрутитися у поведінку is_valid(). Це може бути корисно, якщо потрібно змінити або розширити стандартну логіку валідації.
Розглянемо форму, де потрібно логувати всі спроби відправки форми:
class LoggingForm(forms.Form):
email = forms.EmailField(required=True)
def is_valid(self):
# Логуємо спробу валідації форми
print("Перевіряємо форму...")
# Викликаємо стандартну реалізацію методу
valid = super().is_valid()
if not valid:
print("Помилки: ", self.errors)
return valid
Тепер на кожну спробу перевірки форми виводиться повідомлення в консоль, а у випадку помилок інформація про них доступна розробнику.
Типові помилки при використанні is_valid() та clean()
- Не повертаєте
cleaned_data: якщо забути повернути очищені дані у методіclean(), вони не будуть доступні для подальшого використання. - Відсутній виклик
super(): якщо не викликати реалізацію методуclean()батьківського класу, зникне стандартна логіка валідації. - Помилки з іменами методів: ім'я методу для перевірки поля повинно збігатися з назвою поля, інакше Django його просто пропустить.
- Погано структуровані перевірки: не варто писати складні та громіздкі перевірки в одному методі. Логіку краще розділити на кілька методів.
Практичне завдання
Створіть форму реєстрації користувача:
- Поля: username, email, password, confirm_password.
- Логіка: всі поля обов'язкові, паролі повинні збігатися,
usernameне може бути "admin".
Додайте кастомний метод
clean_email:- Перевірте, щоб в email-адресі був вказаний домен "example.com".
Збереження даних:
- Після успішної валідації збережіть дані користувача в базу даних (вважайте, що модель вже існує).
Приклад використання в реальності: перевірка унікальності імені користувача або email дуже часто зустрічається у формах реєстрації на сайтах. Цей підхід не лише зміцнить ваші знання, але й стане важливим навиком для роботи з реальними проектами.
Тепер вперед! Як тільки зустрінете помилку форми, пам'ятайте: це не баг, це виклик вашій майстерності! 😉
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ