Отправка формы методом POST. Объект request фреймворка flask
Создание html-формы
В форме создания новой статьи нам понадобятся следующие поля и другие интерактивные элементы:
- многострочное текстовое поле для ввода текста статьи,
- поле для заголовка статьи,
- небольшое многострочное текстовое поле для краткого описания содержания статьи,
- поле для адреса статьи, в данном случаи пути (части URL),
- список разделов меню для выбора, в какой из них будет добавлена ссылка на статью,
- поле для указания номера (позиции) статьи в разделе этого меню,
- кнопка для отправки данных на сервер.
Для добавления/правки разделов следовало бы создать отдельную страницу и шаблон под нее, например, 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>
Далее мы будем использовать этот сокращенный вариант при внесении в код формы изменений, связанных с данными. Однако в готовом шаблоне используется более сложное стилевое оформление элементов формы.
Также подключен jQuery-плагин "highlight-within-textarea", с помощью которого настроена подсветка тегов в поле редактирования статьи. Можно было бы установить расширение flask-ckeditor, которое интегрирует CKEditor во фреймворк. Однако, мне не удалось его настроить так, чтобы он создавал удобство без появления дополнительных проблем (подключается только 4-я версия, редактор удаляет тег figure
, в Chrome не отображается). Вероятно проще устанавливать и настраивать CKEditor на стороне фронтенда согласно справке на официальном сайте этого редактора.
Метод POST и объект request
Если сейчас в форме нажать на кнопку "Сохранить", сервер вернет ошибку 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 О сайте Раз два три
Для справки: значением незаполненного поля является пустая строка, числа передаются в виде строки.
Понятно, что данные следует не выводить в терминал, а сохранять в базе данных.
Также, обратите внимание, что при отправке данных, форма загружается в первоначальном виде (одни поля очищаются, другим присваивается значение по-умолчанию). Данные теряются.