Отправка формы методом POST. Объект request фреймворка flask

Создание html-формы

В форме создания новой статьи нам понадобятся следующие поля и другие интерактивные элементы:

Для добавления/правки разделов следовало бы создать отдельную страницу и шаблон под нее, например, menu.html. Однако если разделы правятся не часто, проще изменять их на стороне бэкенда. Кроме того реализация правки меню с помощью технологии drag&drop (что было бы более правильным) не такая уж простая задача фронтенда.

Код формы с минимальным оформлением и ее вид:

<form method="post">
  <p>
    <label for="section">Раздел меню</label>
    <select name="section" id="section" style="font-size:18px;">
      <option selected>Растения</option>
      <option>Животные</option>
      <option>Эволюция</option>
    </select>
  </p>
  <p>
    <label for="position">Позиция в разделе</label>
    <input type="number" required name="position" id="position" value="0"
           style="font-size:18px;width:40px;">
  </p>
  <p>
    <label for="path">https://site.ru/</label>
    <input type="text" name="path" id="path" style="font-size:18px;">
  </p>
  <p>
    <label for="h1">H1</label>
    <input type="text" name="h1" id="h1" style="font-size:20px;width:95%">
  </p>
  <p>
      <textarea name="description" id="description"
                style="width:100%;height:40px;"
                placeholder="Краткое описание"></textarea>
  </p>
  <p>
    <textarea name="article"
              style="font-size:20px;width:100%;height:500px;"></textarea>
  </p>
  <p>
    <input type="submit" value="Сохранить" style="font-size:18px;">
  </p>
</form>
Форма HTML для создания статьи на сайте

Далее мы будем использовать этот сокращенный вариант при внесении в код формы изменений, связанных с данными. Однако в готовом шаблоне (t1-bd) используется более сложное стилевое оформление элементов формы.

Форма в готовом шаблоне сайта на Flask

Также подключен jQuery-плагин "highlight-within-textarea", с помощью которого настроена подсветка тегов в поле редактирования статьи. Можно было бы установить расширение flask-ckeditor, которое интегрирует CKEditor во фреймворк. Однако, мне не удалось его настроить так, чтобы он создавал удобство без появления дополнительных проблем (подключается только 4-я версия, редактор удаляет тег figure, в Chrome не отображается). Вероятно проще устанавливать и настраивать CKEditor на стороне фронтенда согласно справке на официальном сайте этого редактора.

Метод POST и объект request

Если сейчас в форме нажать на кнопку "Сохранить", сервер вернет ошибку 405 "Method Not Allowed" (метод не разрешен).

Возврат сервером ошибки 405 "Method Not Allowed"

Действительно, данные на сервер отправляются методом POST (так указано в теге form), а функции-представления во фреймворке Flask по-умолчанию получают их из запроса, отправленного методом GET. В данном случае мы должны использовать POST не ради секретности данных, а потому что содержание статьи может быть длинным. GET имеет ограничение на объем передаваемых данных.

Чтобы представление работало с обоими методами, следует передать список допустимых для именованного параметра methods декоратора route.

@app.route('/', methods=['GET', 'POST'])

Метод GET также необходим, иначе нельзя будет получить страницу первый раз. Если аргумент будет указан как methods=['POST'], то ответ 405 будет при запросе страницы методом GET.

Объект request

Теперь при POST-запросе данные уходят на сервер, но как к ним обратиться в программе? В модуле flask есть объект request (импортируйте его), созданный от класса Request и предоставляющий доступ к входящим данным. То есть фреймворк парсит поступившие с запросом данные и дает доступ к ним через глобальный объект request.

Значением атрибута form этого объекта является структура похожая на словарь. Имена полей формы выступают в роли ключей. Чтобы увидеть значения, выведем их в консоль:

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        print(request.form['section'])
        print(request.form['position'])
        print(request.form['path'])
        print(request.form['h1'])
        print(request.form['article'])

    return render_template('create.html')

Если заполнить форму и отправить ее, получится что-то вроде этого:

Растения
0
about
О сайте

Раз два три

Для справки: значением незаполненного поля является пустая строка, числа передаются в виде строки.

Понятно, что данные следует не выводить в терминал, а сохранять в базе данных.

Также, обратите внимание, что при отправке данных, форма загружается в первоначальном виде (одни поля очищаются, другим присваивается значение по-умолчанию). Данные теряются.