Обработка форм вручную и валидация

Форма — это диалог: пользователь шлёт данные, сервер их проверяет и либо принимает, либо возвращает с ошибками. Валидация на сервере обязательна всегда.
Никогда не доверяй вводу пользователя. Проверки в браузере (required, pattern) — лишь удобство; их легко обойти. Настоящая защита — серверная валидация: проверь каждое поле, собери ошибки, при провале покажи форму снова с подсказками.

Обработка формы — это цикл: показать (GET) → принять (POST) → проверить → сохранить или вернуть с ошибками. Сначала разберём ручной способ — он показывает механику, которую потом автоматизирует Flask-WTF.

@app.route("/register", methods=["GET", "POST"])
def register():
    errors = {}
    if request.method == "POST":
        name = request.form.get("name", "").strip()
        email = request.form.get("email", "").strip()
        if not name:
            errors["name"] = "Имя обязательно"
        if "@" not in email:
            errors["email"] = "Некорректный email"
        if not errors:
            # сохранить ...
            return redirect(url_for("success"))
    return render_template("register.html", errors=errors)

Логика: накапливаем ошибки в словарь, по каждому полю своя проверка. Если словарь пуст — данные валидны, сохраняем и редиректим (PRG). Иначе — рендерим форму снова, передав ошибки, чтобы шаблон показал подсказки рядом с полями.

Главная аксиома работы с формами: вход пользователя враждебен по умолчанию. Любые проверки на стороне браузера — required, maxlength, pattern — это лишь удобство интерфейса; их обходят за секунду через curl, Postman или вкладку DevTools. Единственная настоящая граница доверия — сервер, и валидацию там делают всегда, для каждого поля. Хорошая обработка формы накапливает сразу все ошибки (а не падает на первой) и при провале возвращает форму вместе с введёнными значениями, чтобы пользователь не заполнял всё заново. Эту ручную механику важно понять до Flask-WTF, потому что расширение автоматизирует ровно её: те же правила, тот же цикл «проверить — принять или вернуть».

Как работает под капотом

Валидация — это набор правил, прогоняемых по полям. Каждое правило либо проходит, либо добавляет ошибку. Решение «принять или вернуть» зависит от того, пуст ли список ошибок.

  POST с данными формы
       │
       ▼
  ┌──────────────────────────┐
  │ для каждого поля:         │
  │   применить правила       │
  │   ошибка? → errors[поле]  │
  └──────────────────────────┘
       │
   errors пуст? ──да──▶ сохранить → redirect (PRG)
       │
       нет
       ▼
  показать форму снова + ошибки + введённые данные

Смоделируем валидатор обычным Python — это ровно та логика, что внутри ручной обработки и Flask-WTF.

def validate(form):
    errors = {}
    name = form.get("name", "").strip()
    email = form.get("email", "").strip()
    age = form.get("age", "").strip()

    if not name:
        errors["name"] = "Имя обязательно"
    if "@" not in email or "." not in email:
        errors["email"] = "Некорректный email"
    if not age.isdigit() or int(age) < 0:
        errors["age"] = "Возраст должен быть числом"
    return errors

print(validate({"name": "Анна", "email": "[email protected]", "age": "20"}))  # {}
print(validate({"name": "", "email": "bad", "age": "x"}))

Запусти: валидные данные дают пустой словарь (всё ок), кривые — словарь ошибок по полям. Пустой словарь = зелёный свет на сохранение. Это сердце любой обработки формы.

Частые ошибки

  • Полагаться только на проверки браузера. Их обходят за секунду через curl или DevTools. Серверная валидация обязательна.
  • Терять введённые данные при ошибке. Верни значения обратно в шаблон, иначе пользователь заполняет всё заново.
  • Не делать strip(). Пробелы по краям ломают проверки «непустое поле».

Best practices

  • Валидируй на сервере всегда, даже если есть проверки в HTML.
  • Накапливай все ошибки сразу, а не показывай по одной.
  • При провале возвращай и ошибки, и ранее введённые значения.

Что запомнить

  • Серверная валидация обязательна: вход пользователя нельзя считать безопасным.
  • Ошибки накапливают по полям; пустой список ошибок = можно сохранять.
  • При провале форму показывают снова с ошибками и введёнными данными.
  • После успешного сохранения — редирект (PRG).

Итог: обработка формы — это валидация на сервере с накоплением ошибок и повторным показом при провале. Ручной способ раскрывает механику; дальше Flask-WTF автоматизирует её и добавит защиту от CSRF.

Проверьте себя
1. Почему серверная валидация обязательна, даже если есть проверки в браузере?
AБраузерные проверки медленные
BПроверки в браузере легко обойти (curl, DevTools) — серверу нельзя доверять входу
CТак требует Jinja2
DСервер не умеет показывать формы
2. Что нужно сделать при провале валидации формы?
AОчистить все поля и показать пустую форму
BПоказать форму снова с ошибками и ранее введёнными данными
CСразу сохранить данные
DВернуть код 500