Инфраструктура сообщений ¶
Обычно веб-приложениям необходимо отображать уведомления (также называемые «флэш-сообщениями») для пользователей после обработки формы или другого типа пользовательского ввода.
Для этого Django предлагает полную поддержку сообщений, хранящихся в файлах cookie или в сеансах, как для анонимных, так и для зарегистрированных пользователей. Инфраструктура сообщений позволяет временно сохранять сообщения в запросе, а затем извлекать их в следующем запросе (обычно следующем) для их отображения. Каждое сообщение помечено определенным уровнем, определяющим его приоритет (например 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 байт.
-
класс
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 AuthorCreate(SuccessMessageMixin, CreateView):
model = Author
success_url = '/success/'
success_message = "%(name)s was created successfully"
Очищенные данные form
доступны для интерполяции строк с синтаксисом %(nom_champ)s
. Для них ModelForm
, если вам нужно получить доступ к полям зарегистрированного объекта, переопределите метод 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 ComplicatedCreate(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, где каждое окно / вкладка имеет свой собственный контекст просмотра.