Глава 22 · Веб-разработка с Python

HTML-формы и отправка данных на сервер

От HTML-формы до сохранённых данных — и почему после сохранения нужен ещё один запрос.

Раздел 22.2 показал HTML-форму, раздел 22.5 — маршрут, который её принимает. Теперь разберём этот путь целиком, с одной важной деталью: что делать после того, как форма обработана.

templates/forma.html
<form action="{{ url_for('dobavit') }}" method="post">
  <label for="zadacha">Новая задача</label>
  <input type="text" id="zadacha" name="zadacha" required>
  <button type="submit">Добавить</button>
</form>

method="post" говорит браузеру отправить данные формы как тело POST-запроса, а не как часть адреса. Атрибут name="zadacha" у поля определяет ключ, под которым значение придёт на сервер.

app.py
@app.route("/dobavit", methods=["POST"])
def dobavit():
    novaya_zadacha = request.form.get("zadacha", "").strip()
    if novaya_zadacha:
        zadachi.append(novaya_zadacha)
    return redirect(url_for("glavnaya"), code=303)

request.form.get("zadacha", "") достаёт значение поля по имени; второй аргумент — что вернуть, если поля вообще не было. Какие ещё проверки стоит добавить перед тем, как сохранять введённое значение — в разделе 22.31.

POST-Redirect-GET — зачем нужен redirect в конце

Обработчик формы заканчивается не отрисовкой страницы, а redirect(url_for("glavnaya"), code=303) — HTTP-ответом с кодом 303 See Other (раздел 22.9), который сообщает браузеру адрес, откуда нужно запросить результат методом GET. Браузер выполняет второй, уже безопасный запрос и показывает страницу.

Браузер
POST /dobavit
с данными формы
Flask
сохраняет задачу
303 See Other, Location: /
Браузер
GET /
уже без формы
Flask
показывает список
POST-Redirect-GET: два отдельных запроса вместо одного
Без redirect повторная отправка дублирует данные
Если обработчик POST-запроса сразу возвращает готовую страницу (а не делает redirect), браузер связывает уже показанную страницу именно с этим POST-запросом — и обновление страницы (F5) отправит форму ещё раз, молча продублировав задачу. Redirect гарантирует, что после ответа сервера текущей операцией браузера окажется безопасный GET, который можно повторять сколько угодно.
Практика: форма и POST-Redirect-GET
Модуль flask не установлен в браузерном окружении Pyodide — выполните локально в VS Code, PyCharm или Jupyter
Практика выполняется локально
Открыть практику →