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