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