Фреймворк сообщений ¶
Довольно часто в веб-приложениях вам необходимо отображать одноразовое уведомление (также известное как «флэш-сообщение») для пользователя после обработки формы или некоторых других типов пользовательского ввода.
Для этого Django обеспечивает полную поддержку обмена сообщениями на основе файлов cookie и сеансов как для анонимных, так и для аутентифицированных пользователей. Инфраструктура сообщений позволяет вам временно хранить сообщения в одном запросе и извлекать их для отображения в следующем запросе (обычно в следующем). Каждое сообщение помечается специфично , level
что определяет его приоритет (например, info
,
warning
или error
).
Включение сообщений ¶
Сообщения реализуются через промежуточный класс и соответствующий контекстный процессор .
Значение по умолчанию, settings.py
созданное с помощью,
уже содержит все настройки, необходимые для включения функции сообщений:django-admin startproject
'django.contrib.messages'
находится вINSTALLED_APPS
.MIDDLEWARE
содержит'django.contrib.sessions.middleware.SessionMiddleware'
и'django.contrib.messages.middleware.MessageMiddleware'
.Бэкэнд хранилища по умолчанию полагается на сеансы . Вот почему он
SessionMiddleware
должен быть включен и появляться раньшеMessageMiddleware
вMIDDLEWARE
.'context_processors'
Вариант вDjangoTemplates
интерфейсе , определенном вTEMPLATES
настройке содержит'django.contrib.messages.context_processors.messages'
.
Если вы не хотите использовать сообщения, вы можете удалить
'django.contrib.messages'
из своего INSTALLED_APPS
,
MessageMiddleware
строку из MIDDLEWARE
и messages
обработчик контекста из TEMPLATES
.
Настройка движка сообщений ¶
Бэкэнды хранения ¶
Фреймворк сообщений может использовать разные серверные части для хранения временных сообщений.
Django предоставляет три встроенных класса хранения
django.contrib.messages
:
-
класс
storage.session.
SessionStorage
¶ Этот класс хранит все сообщения внутри сеанса запроса. Поэтому для этого требуется
contrib.sessions
приложение Django .
Этот класс хранит данные сообщения в файле cookie (подписанном секретным хешем для предотвращения манипуляций) для сохранения уведомлений между запросами. Старые сообщения удаляются, если размер данных cookie превышает 2048 байт.
Изменено в Django 3.2:Формат сообщений изменен на Формат, соответствующий RFC 6265 .
-
класс
storage.fallback.
FallbackStorage
¶ Этот класс сначала использует
CookieStorage
, а затем возвращается к использованиюSessionStorage
для сообщений, которые не могут поместиться в один файл cookie. Также требуетсяcontrib.sessions
приложение Django .Это поведение позволяет избежать записи в сеанс, когда это возможно. Он должен обеспечивать наилучшую производительность в общем случае.
FallbackStorage
- класс хранения по умолчанию. Если он вам не подходит, вы можете выбрать другой класс хранилища, установив MESSAGE_STORAGE
его полный путь импорта, например:
MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'
-
класс
storage.base.
BaseStorage
¶
Для того, чтобы написать свой собственный класс хранения, подкласс BaseStorage
класса в
django.contrib.messages.storage.base
и реализовать _get
и
_store
методы.
Уровни сообщений ¶
Инфраструктура сообщений основана на конфигурируемой архитектуре уровня, аналогичной архитектуре модуля ведения журнала Python. Уровни сообщений позволяют группировать сообщения по типу, чтобы их можно было фильтровать или по-разному отображать в представлениях и шаблонах.
Встроенные уровни, которые можно импортировать django.contrib.messages
напрямую:
Постоянный | Цель |
---|---|
DEBUG |
Сообщения, связанные с разработкой, которые будут проигнорированы (или удалены) в производственном развертывании. |
INFO |
Информационные сообщения для пользователя |
SUCCESS |
Действие выполнено успешно, например «Ваш профиль успешно обновлен» |
WARNING |
Неисправности не было, но она может быть неизбежной |
ERROR |
Действие не было успешным или произошел другой сбой |
Этот MESSAGE_LEVEL
параметр можно использовать для изменения минимального записываемого уровня (или его можно изменить по запросу ). Попытки добавить сообщения более низкого уровня будут игнорироваться.
Теги сообщений ¶
Теги сообщений - это строковое представление уровня сообщения плюс любые дополнительные теги, которые были добавлены непосредственно в представление ( дополнительные сведения см. В разделе Добавление дополнительных тегов сообщений ниже). Теги хранятся в строке и разделяются пробелами. Обычно теги сообщений используются как классы CSS для настройки стиля сообщения в зависимости от типа сообщения. По умолчанию каждый уровень имеет один тег, который представляет собой строчную версию собственной константы:
Постоянная уровня | Тег |
---|---|
DEBUG |
debug |
INFO |
info |
SUCCESS |
success |
WARNING |
warning |
ERROR |
error |
Чтобы изменить теги по умолчанию для уровня сообщения (встроенного или настраиваемого), установите MESSAGE_TAGS
значение словаря, содержащего уровни, которые вы хотите изменить. Поскольку это расширяет теги по умолчанию, вам нужно предоставить теги только для уровней, которые вы хотите переопределить:
from django.contrib.messages import constants as messages
MESSAGE_TAGS = {
messages.INFO: '',
50: 'critical',
}
Использование сообщений в представлениях и шаблонах ¶
-
add_message
( запрос , уровень , сообщение , extra_tags = '' , fail_silently = False ) ¶
Добавление сообщения ¶
Чтобы добавить сообщение, позвоните:
from django.contrib import messages
messages.add_message(request, messages.INFO, 'Hello world.')
Некоторые методы быстрого доступа предоставляют стандартный способ добавления сообщений с часто используемыми тегами (которые обычно представлены в виде HTML-классов для сообщения):
messages.debug(request, '%s SQL statements were executed.' % count)
messages.info(request, 'Three credits remain in your account.')
messages.success(request, 'Profile details updated.')
messages.warning(request, 'Your account expires in three days.')
messages.error(request, 'Document deleted.')
Отображение сообщений ¶
-
get_messages
( запрос ) ¶
В вашем шаблоне используйте что-то вроде:
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
Если вы используете обработчик контекста, ваш шаблон должен отображаться с расширением
RequestContext
. В противном случае убедитесь, messages
что доступен контекст шаблона.
Даже если вы знаете, что есть только одно сообщение, вы все равно должны перебирать
messages
последовательность, потому что в противном случае хранилище сообщений не будет очищено для следующего запроса.
Контекстный процессор также предоставляет DEFAULT_MESSAGE_LEVELS
переменную, которая отображает имена уровней сообщений на их числовые значения:
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}Important: {% endif %}
{{ message }}
</li>
{% endfor %}
</ul>
{% endif %}
Вне шаблонов вы можете использовать
get_messages()
:
from django.contrib.messages import get_messages
storage = get_messages(request)
for message in storage:
do_something_with_the_message(message)
Например, вы можете получить все сообщения, чтобы вернуть их в
JSONResponseMixin вместо
файлаTemplateResponseMixin
.
get_messages()
вернет экземпляр настроенной серверной части хранилища.
Message
Класс ¶
-
класс
storage.base.
Message
¶ Когда вы перебираете список сообщений в шаблоне, вы получаете экземпляры
Message
класса. У них всего несколько атрибутов:message
: Фактический текст сообщения.level
: Целое число, описывающее тип сообщения (см. Раздел уровней сообщений выше).tags
: Строка, объединяющая все теги сообщения (extra_tags
иlevel_tag
), разделенные пробелами.extra_tags
: Строка, содержащая настраиваемые теги для этого сообщения, разделенные пробелами. По умолчанию он пуст.level_tag
: Строковое представление уровня. По умолчанию это строчная версия имени связанной константы, но при необходимости это можно изменить с помощьюMESSAGE_TAGS
параметра.
Создание пользовательских уровней сообщений ¶
Уровни сообщений - это не что иное, как целые числа, поэтому вы можете определить свои собственные константы уровня и использовать их для создания более настраиваемых отзывов пользователей, например:
CRITICAL = 50
def my_view(request):
messages.add_message(request, CRITICAL, 'A serious error occurred.')
При создании пользовательских уровней сообщений следует соблюдать осторожность, чтобы не перегружать существующие уровни. Значения для встроенных уровней:
Постоянная уровня | Значение |
---|---|
DEBUG |
10 |
INFO |
20 |
SUCCESS |
25 |
WARNING |
30 |
ERROR |
40 |
Если вам нужно идентифицировать настраиваемые уровни в вашем HTML или CSS, вам необходимо предоставить сопоставление с помощью MESSAGE_TAGS
параметра.
Примечание
Если вы создаете приложение многократного использования, рекомендуется использовать только встроенные уровни сообщений и не полагаться на какие-либо настраиваемые уровни.
Изменение минимального записываемого уровня по запросу ¶
Минимальный записываемый уровень может быть установлен для каждого запроса с помощью set_level
метода:
from django.contrib import messages
# Change the messages level to ensure the debug message is added.
messages.set_level(request, messages.DEBUG)
messages.debug(request, 'Test message...')
# In another request, record only messages with a level of WARNING and higher
messages.set_level(request, messages.WARNING)
messages.success(request, 'Your profile was updated.') # ignored
messages.warning(request, 'Your account is about to expire.') # recorded
# Set the messages level back to default.
messages.set_level(request, None)
Точно так же текущий эффективный уровень можно получить с помощью get_level
:
from django.contrib import messages
current_level = messages.get_level(request)
Для получения дополнительной информации о том, как работает минимальный записанный уровень, см. Уровни сообщений выше.
Добавление дополнительных тегов сообщений ¶
Для более прямого управления тегами сообщений вы можете дополнительно предоставить строку, содержащую дополнительные теги, любому из методов добавления:
messages.add_message(request, messages.INFO, 'Over 9000!', extra_tags='dragonball')
messages.error(request, 'Email box full', extra_tags='email')
Дополнительные теги добавляются перед тегом по умолчанию для этого уровня и разделяются пробелом.
Тихая ошибка при отключенной структуре сообщений ¶
Если вы пишете многоразовое приложение (или другой фрагмент кода) и хотите включить функцию обмена сообщениями, но не хотите, чтобы ваши пользователи включали ее, если они этого не хотят, вы можете передать дополнительный аргумент ключевого слова
fail_silently=True
в любой из add_message
семейства методов. Например:
messages.add_message(
request, messages.SUCCESS, 'Profile details updated.',
fail_silently=True,
)
messages.info(request, 'Hello world.', fail_silently=True)
Примечание
Параметр fail_silently=True
скрывает только то MessageFailure
, что в противном случае произошло бы, когда структура сообщений отключена и кто-то пытается использовать один из add_message
семейства методов. Он не скрывает сбоев, которые могут возникнуть по другим причинам.
Добавление сообщений в представления на основе классов ¶
-
класс
views.
SuccessMessageMixin
¶ Добавляет атрибут сообщения об успехе в
FormView
базируемые классы-
get_success_message
( cleaned_data ) ¶ cleaned_data
это очищенные данные из формы, которая используется для форматирования строк
-
Пример views.py :
from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.edit import CreateView
from myapp.models import Author
class AuthorCreateView(SuccessMessageMixin, CreateView):
model = Author
success_url = '/success/'
success_message = "%(name)s was created successfully"
Очищенные данные из form
доступны для строковой интерполяции с использованием %(field_name)s
синтаксиса. Для ModelForms, если вам нужен доступ к полям из сохраненного, object
переопределите
get_success_message()
метод.
Пример views.py для ModelForms :
from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.edit import CreateView
from myapp.models import ComplicatedModel
class ComplicatedCreateView(SuccessMessageMixin, CreateView):
model = ComplicatedModel
success_url = '/success/'
success_message = "%(calculated_field)s was created successfully"
def get_success_message(self, cleaned_data):
return self.success_message % dict(
cleaned_data,
calculated_field=self.object.calculated_field,
)
Срок действия сообщений ¶
Сообщения помечаются как подлежащие очистке при итерации экземпляра хранилища (и очищаются при обработке ответа).
Чтобы избежать очистки сообщений, вы можете установить для хранилища сообщений значение
False
после итерации:
storage = messages.get_messages(request)
for message in storage:
do_something_with(message)
storage.used = False
Поведение параллельных запросов ¶
Из-за того, как работают файлы cookie (и, следовательно, сеансы), поведение любых бэкэндов, использующих файлы cookie или сеансы, не определено, когда один и тот же клиент выполняет несколько запросов, которые устанавливают или получают сообщения параллельно . Например, если клиент инициирует запрос, который создает сообщение в одном окне (или вкладке), а затем другой, который извлекает любые неитерированные сообщения в другом окне, до перенаправления первого окна, сообщение может появиться во втором окне вместо первого. окно, где его можно ожидать.
Короче говоря, когда задействовано несколько одновременных запросов от одного и того же клиента, не гарантируется, что сообщения будут доставлены в то же окно, которое их создало, а в некоторых случаях - вообще. Обратите внимание, что это обычно не проблема для большинства приложений и перестанет быть проблемой в HTML5, где каждое окно / вкладка будет иметь свой собственный контекст просмотра.