Объект request в Jinja
Когда страница сайта запрашивается методом POST, то веб-серверу, а потом и flask-приложению, передаются данные из формы. Далее они доступны через объект request
.
По-идее значение каждого поля должно сохраняться в соответствующую ячейку записи таблицы БД. Однако перед этим данные следует проверять на корректность. Например, мы не хотим, чтобы производилась запись в БД, если заголовок статьи пуст.
При отправке формы веб-страница в нашем случае перезагружается (хотя часто в случае POST-запроса выполняют перенаправление на другую страницу). При этом форма очищается. Если мы не записываем в БД статью без заголовка, но человек потратил время на ввод содержимого статьи, оно не должно быть утеряно. Данные следует вернуть в форму, то есть ранее заполненные поля должны снова оказаться точно также заполненными. Кроме того, пользователь должен увидеть пояснение, что не так с передаваемыми данными.
Сначала реализуем возврат данных в форму. Jinja в шаблонах также имеет доступ к объекту request
, поэтому перепишем форму таким образом (переменные должны определяться до их использования, у нас h1 используется в блоке title):
{% if request.form %} {% set sel = request.form['section'] | int %} {% set pos = request.form['position'] %} {% set path = request.form['path'] %} {% set h1 = request.form['h1'] %} {% set desc = request.form['description'] %} {% set article = request.form['article'] %} {% endif %} ... <form method="post"> <p> <label for="section">Раздел меню</label> <select name="section" id="section" style="font-size:18px;"> {% for s in sections %} <option value="{{ s[0] }}" {% if sel == s[0] %} selected {% endif %}>{{ s[1] }}</option> {% endfor %} </select> </p> <p> <label for="position">Позиция в разделе</label> <input type="number" required name="position" id="position" style="font-size:18px;width:40px;" value="{% if pos %}{{ pos }}{% else %}0{% endif %}"> </p> <p> <label for="path">https://site.ru/</label> <input type="text" name="path" id="path" style="font-size:18px;" value="{{ path }}"> </p> <p> <label for="h1">H1</label> <input type="text" name="h1" id="h1" style="font-size:20px;width:95%" value="{{ h1 }}"> </p> <p> <textarea name="description" id="description" style="font-size:18px;width:100%;height:40px;" placeholder="Краткое описание" >{{ desc }}</textarea> </p> <p> <textarea name="article" style="font-size:18px;width:100%;height:500px;" >{{ article }}</textarea> </p> <p> <input type="submit" value="Сохранить" style="font-size:18px;"> </p> </form>
Когда страница запрашивается методом GET, в объекте request.form
нет элементов с ключами path, h1, article и др. Jinja (но не python-программа) в этом случае игнорирует обращение к ним, главное ‒ чтобы их значение (которого нет) не участвовало ни в каких операциях. Поскольку значение section строкового типа, а сравниваемый с ним номер раздела из таблицы БД имеет числовой тип, мы заранее приводим значение section к типу int
. При этом синтаксис Jinja отличается от Python. Здесь нельзя просто вызвать функцию int()
.
Также в примере вы можете увидеть особенности использования в Jinja ветвления if-else. Так, если значение position существует, присваиваем его полю, иначе ‒ 0.
То, что находится в двойных фигурных скобках, выводится в html-документ. Если команды заключены в фигурные скобки со знаками процента ‒ это "внутренние" инструкции шаблонизатора.
Теперь, если страница загружается методом GET (Enter в адресной строке браузера), то форма будет очищаться, так как request.form
пуст. Если же страница загружается после нажатия кнопки "Сохранить", то данные в форме остаются такими, какими были до ее нажатия.