Модуль 23

Валідація форм та кастомні валідатори

Ось урок у стилі CS50, створений спеціально за твоїм запитом.


🎓 CS50-style: Валідація форм та кастомні валідатори

👋 Привіт, світе! Радий бачити вас.

Сьогодні ми говоримо про одну з найважливіших тем у розробці — про довіру. А точніше — про її відсутність. Як ми, розробники, маємо ставитися до даних, які надходять від користувачів?

Спойлер: Ми не віримо нікому.


1. 🔥 Вступ: Фейс-контроль вашого коду

Уявіть, що ви власник елітного нічного клубу. У вас всередині дорога техніка, ідеальна атмосфера, вишукані напої (це ваша База Даних і Сервер).

На вході стоїть охоронець. Його завдання — перевіряти гостей. А тепер уявіть, що охоронець заснув. У клуб заходять усі підряд: * Хлопець, який приніс із собою живого єнота. * Хтось, хто намагається пройти за квитком, намальованим на серветці. * Людина, яка стверджує, що їй "-5 років".

Що станеться всередині? Хаос. Єнот перегризе дроти, напої розіллють, вечірка закінчиться катастрофою.

У програмуванні це виглядає так: Користувач вводить у поле "Вік" слово "двадцять", ваша програма намагається помножити "двадцять" на 365 днів і... CRASH! 💥 Система падає.

Риторичне питання: Ви б дозволили пасажиру сісти в літак, якби в його паспорті замість імені було написано DROP TABLE users;?

Ось навіщо нам потрібна Валідація. Це наш охоронець. Це набір правил, які кажуть: "Ти проходиш, а ти — ні, і ось чому". Без цього будь-яка програма — це картковий будинок.


2. 🧠 Теоретична база (Що там під капотом?)

Давайте розберемося, як це працює, не занурюючись у нудні визначення.

Валідація — це процес перевірки даних на відповідність певним критеріям перед тим, як пустити їх у систему.

Де живе наш "охоронець"?

Важливо розуміти, що є два рубежі оборони:

  1. Frontend (Клієнтська частина):

    • Аналогія: Це табличка на дверях "Вхід тільки у краватках".
    • Мета: Швидкість і зручність. Користувач одразу бачить червону рамку, якщо забув ввести @ в email.
    • Проблема: Цю перевірку легко обійти (хакер може вимкнути JavaScript). Ніколи не покладайтеся тільки на неї!
  2. Backend (Серверна частина):

    • Аналогія: Це суворий вишибала всередині, який перевіряє паспорт під ультрафіолетом.
    • Мета: Безпека і цілісність даних.
    • Правило: Це обов'язково.

Що таке "Кастомний валідатор"?

Стандартні валідатори — це нудно: "поле не пусте", "це число", "довжина > 5". Але життя складніше. * А що, якщо пароль не може містити ваше ім'я? * А що, якщо дата вильоту не може бути раніше, ніж сьогодні? * А що, якщо обраний нікнейм вже зайнятий іншим користувачем?

Ось тут вступають кастомні (власні) валідатори. Це функції, які ви пишете самі для специфічної бізнес-логіки.

Запам'ятайте головне: Валідатор — це функція, яка приймає дані і повертає або True (все ок), або Помилку (опис проблеми).


3. 🧪 Приклади (Let's verify!)

Давайте подивимось на код. Я використовуватиму псевдокод, схожий на Python, щоб ми зосередились на логіці.

Рівень 1: Проста перевірка (Basic)

У нас є форма реєстрації. Потрібно перевірити вік.

# Дані від користувача
user_age_input = "15"

# Логіка валідації
def validate_age(age):
    if not age.isdigit(): # Перевіряємо, чи це цифри
        return "Помилка: Вік має бути числом."

    age_number = int(age)

    if age_number < 18:
        return "Помилка: Ви занадто молоді для цього сервісу."

    return None # Все чисто!

# Використання
result = validate_age(user_age_input)
if result:
    print(result) # Виведе: Помилка: Ви занадто молоді...
else:
    print("Ласкаво просимо!")

Очікувано? Так. Якщо менше 18 — не пускаємо.


Рівень 2: Реальний приклад (Складніша логіка)

Реєстрація на конференцію. Email має бути корпоративним (закінчуватися на @company.com).

def validate_corporate_email(email):
    if "@" not in email:
        return "Це взагалі не схоже на пошту."

    domain = email.split("@")[1] # Беремо частину після @

    if domain != "company.com":
        return "Доступ дозволено лише працівникам компанії!"

    return None

Тут ми вже не просто перевіряємо формат, ми перевіряємо зміст.


Рівень 3: Кастомний валідатор (Custom Validator)

Задача: Створити систему зміни пароля. Умова: Новий пароль не може бути таким самим, як старий.

# Уявіть, що це частина класу або форми
class ChangePasswordForm:
    def __init__(self, old_pass, new_pass):
        self.old_pass = old_pass
        self.new_pass = new_pass

    # Наш кастомний валідатор
    def validate(self):
        errors = []

        # Стандартна перевірка
        if len(self.new_pass) < 8:
            errors.append("Пароль надто короткий.")

        # КАСТОМНА логіка
        if self.new_pass == self.old_pass:
            errors.append("Новий пароль не може співпадати зі старим!")

        return errors

# Тестуємо
form = ChangePasswordForm("secret123", "secret123")
print(form.validate()) 
# Очікуємо: ['Новий пароль не може співпадати зі старим!']

Бачите? Валідатор — це просто "суддя", який дивиться на два поля одночасно і виносить вирок.


4. 🛠 Практична частина

Тепер ваша черга. Не бійтеся помилятися, компілятор вас не вкусить.

Завдання 1: "Мінімалка" Напишіть функцію validate_username(name), яка перевіряє, щоб ім'я користувача було не коротшим за 3 символи. Якщо коротше — повертає текст помилки.

Завдання 2: "Діапазон" Напишіть валідатор для інтернет-магазину validate_quantity(qty). Кількість товару не може бути 0 і не може бути більше 100 (бо стільки немає на складі).

Завдання 3: "Виправ баг" У коді нижче є логічна помилка. Знайдіть її.

def validate_discount(percent):
    # Знижка має бути від 0 до 50%
    if percent > 0 or percent < 50: # <--- Уважно подивіться сюди
        return True
    return False

Підказка: А що, якщо я введу 99%? Чи пропустить це умова or?

Завдання 4: Міні-кейс "Календар" Напишіть кастомний валідатор, який приймає дві дати: start_date і end_date. Правило: Дата закінчення події не може бути раніше за дату початку.

Завдання 5: "А що, якщо..." Уявіть, що ви робите поле для вводу номера телефону. Користувач може ввести +38067..., або 067..., або (067).... Як би ви підійшли до валідації? 1. Змусити користувача вводити тільки цифри? 2. Або очистити ввід від дужок і пробілів перед перевіркою? (Подумайте, що краще для UX).


5. 💡 Мислення як у розробника

Як відрізнити новачка від профі в цій темі?

⛔ Помилка новачка: Новачок думає: "Я додав атрибут required у HTML тег input, тепер все безпечно". Хакер відкриває консоль браузера, видаляє цей атрибут і відправляє порожній запит. Сервер падає. Урок: Frontend-валідація — це для краси. Backend-валідація — це закон.

⛔ Помилка новачка №2: Повідомлення про помилку: "Invalid Data". Користувач сидить і плаче, бо не розуміє, що саме не так. Порада: Будьте конкретними. "Пароль має містити хоча б одну цифру" — це хороше повідомлення.

🧠 Як думає профі: Профі використовує підхід "Sanitization -> Validation". 1. Санітарна обробка (Sanitization): Користувач ввів " Davyd " (з пробілами). Ми мовчки прибираємо пробіли (trim). 2. Валідація: Тепер перевіряємо чисті дані. Профі знає: користувачі не хочуть ламати ваш сайт, вони просто неуважні. Допоможіть їм.


6. 🧩 Підсумок

Отже, що ми сьогодні забрали з собою?

  1. Дані — це "брудний" матеріал. Ми повинні їх фільтрувати.
  2. Валідація — це щит. Вона буває на клієнті (для зручності) і на сервері (для безпеки).
  3. Кастомні валідатори дозволяють нам впроваджувати бізнес-правила (порівнювати поля, перевіряти логіку).

Тепер ви вмієте не просто приймати дані, а захищати свою програму від хаосу.

Що далі? Ми навчилися перевіряти дані. Але куди їх подіти, коли вони пройшли перевірку? На наступному уроці ми відкриємо двері до святая святих — Баз Даних та SQL. Там ми навчимося зберігати ці ідеально чисті дані на віки.

А поки що — це був CS50! 🎤 (уявне падіння мікрофона)