Сообщить об ошибке.

Система всплывающих сообщений во Flask

Хорошие веб-приложения и пользовательские интерфейсы основаны на обратной связи. Если пользователь не получит достаточной обратной связи, он, в конечном итоге, уйдет с сайта. Фреймворк Flask предоставляет простой способ дать обратную связь пользователю с помощью системы всплывающих сообщений. Эта система позволяет записывать сообщение в конце запроса и получать доступ к нему, только при следующем запросе. Обычно эта система работает в связке с шаблоном (template), который и делает это. Обратите внимание, что браузеры, а иногда и веб-серверы устанавливают ограничение на размер файлов cookie. Это означает, что всплывающие сообщения, которые слишком велики для сессионных файлов cookie, приводят к тому, что сообщения не выводятся без уведомления браузера.

Содержание:

Пример реализации всплывающих сообщений в приложении Flask.

Ниже приведен пример веб-приложения, реализующий систему всплывающих сообщений фреймворка Flask. Примеры кода снабжены комментариями.

from flask import (
            Flask, 
            flash, # система сообщений
            redirect, 
            render_template, 
            request, 
            url_for)

app = Flask(__name__)
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
    error = None
    if request.method == 'POST':
        if request.form['username'] != 'admin' or \
                request.form['password'] != 'secret':
            error = 'Неверные учетные данные'
        else:
            {# #}
            flash('Вы успешно вошли в систему')
            return redirect(url_for('index'))
    return render_template('login.html', error=error)

Определяем базовый шаблон layout.html, который творит чудеса:

{# базовый шаблон layout.html  #}
<!doctype html>
<title>Приложение</title>
{# подключение системы всплывающих сообщений #}
{% with messages = get_flashed_messages() %}
  {% if messages %}
    <ul class=flashes>
    {% for message in messages %}
      <li>{{ message }}</li>
    {% endfor %}
    </ul>
  {% endif %}
{% endwith %}
{# дальше идет основной контент сайта #}
{% block body %}{% endblock %}

Определяем шаблон index.html, унаследованный от layout.html:

{# шаблон index.html  #}
{% extends "layout.html" %}
{# переопределяем блок body #}
{% block body %}
  <h1>Overview</h1>
  <p>Вы хотите <a href="{{ url_for('login') }}">авторизоваться?</a></p>
{% endblock %}

Определяем шаблон login.html, который также наследуется от layout.html:

{# шаблон login.html  #}
{% extends "layout.html" %}
{# переопределяем блок body #}
{% block body %}
  <h1>Login</h1>
  {% if error %}
    <p class=error><strong>Произошла ошибка:</strong> {{ error }}</p>
  {% endif %}
  <form method=post>
    <dl>
      <dt>Пользователь:</dt>
      <dd><input type=text name=username value="{{
          request.form.username }}"></dd>
      <dt>Пароль:</dt>
      <dd><input type=password name=password></dd>
    </dl>
    <p><input type=submit value="Войти"></p>
  </form>
{% endblock %}

Деление всплывающих сообщений на категории.

Также можно указать категории (например: 'error', 'success', 'warning') при отображении сообщения. Если ничего не указано, то категория по умолчанию - это 'message'. Можно использовать альтернативные категории, чтобы дать пользователю лучшую обратную связь. Например, сообщения об ошибках 'error' могут отображаться на красном фоне.

Чтобы вывести сообщение с другой категорией, используйте второй аргумент функции flask.flash():

# код в функции-представлении
flash('Указан неверный пароль', 'error')

Затем внутри шаблона нужно указать функции flask.get_flashed_messages(), чтобы она возвращала сообщение с категорией. В этой ситуации цикл будет выглядеть немного иначе:

<style>.error {background-color: red;}</style>
{% with messages = get_flashed_messages(with_categories=true) %}
  {% if messages %}
    <ul class=flashes>
    {# теперь переменная `messages` категорию и
       соответствующее сообщение #}
    {% for category, message in messages %}
      <li class="{{ category }}">{{ message }}</li>
      {# код выше генерирует вывод: #}
      {# <li class="error">Указан неверный пароль</li> #}
    {% endfor %}
    </ul>
  {% endif %}
{% endwith %}

Это один из примеров того, как визуализировать всплывающие сообщения. Можно также использовать категорию для добавления в сообщение префикса, такого как <strong>Error:</strong>.

Фильтрация всплывающих сообщений.

При желании можно передать список категорий в функцию flask.get_flashed_messages(), которая будет фильтровать результаты. Это полезно, если необходимо отобразить каждую категорию в отдельном блоке шаблона.

Пример реализации фильтрация сообщений.

{% with errors = get_flashed_messages(category_filter=["error"]) %}
{% if errors %}
<div class="alert-message block-message error">
  <a class="close" href="#">×</a>
  <ul>
    {%- for msg in errors %}
    <li>{{ msg }}</li>
    {% endfor -%}
  </ul>
</div>
{% endif %}
{% endwith %}

Функции, реализующие систему сообщений Flask.

flask.flash(message, category='message'):

Готовит сообщение message к показу в следующем запросе к сайту. Чтобы удалить мигающее сообщение из сессии/сеанса и вывести/показать его пользователю, шаблон должен вызвать функцию flask.get_flashed_messages().

Аргументы:

  • message - сообщение, которое нужно вывести.
  • category - категория сообщения, можно использовать любую строку. Рекомендуются следующие значения:
    • 'message' для любого типа сообщения,
    • 'error' для ошибок,
    • 'info' для информационных сообщений
    • 'warning' для предупреждений.

flask.get_flashed_messages(with_categories=False, category_filter=()):

Извлекает все сообщения из сессии и возвращает их. Дальнейшие вызовы в том же запросе функции вернут те же сообщения. По умолчанию возвращаются только сообщения, но если для аргумента with_categories установлено значение True, то возвращаемое значение будет представлять собой список кортежей в форме [(category, message), (category, message) ...].

Можно фильтровать всплывающие сообщения по одной или нескольким категориям, если указать эти категории в аргументе category_filter. Это позволяет отображать категории в отдельных блоках HTML. Аргументы with_categories и category_filter различны:

  • with_categories - контролирует, возвращаются ли категории с текстом сообщения (True возвращает кортеж, а False возвращает только текст сообщения).
  • category_filter - фильтрует только те сообщения, которые соответствуют указанным категориям.

Пример фильтрации сообщений на основе категорий смотрите выше в подразделе "Фильтрация всплывающих сообщений".