Объект 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 пуст. Если же страница загружается после нажатия кнопки "Сохранить", то данные в форме остаются такими, какими были до ее нажатия.

Flask для начинающих




Все разделы сайта