• 3.2
  • 5.0
  • 6.1
  • Версия документации: 3.1

Структура сообщений

Довольно часто в веб-приложениях вам необходимо отобразить пользователю одноразовое уведомление (также известное как «мгновенное сообщение») после обработки формы или некоторых других типов пользовательского ввода.

Для этого Django обеспечивает полную поддержку обмена сообщениями на основе файлов cookie и сеансов как для анонимных, так и для аутентифицированных пользователей. Фреймворк сообщений позволяет временно хранить сообщения в одном запросе и извлекать их для отображения в последующем запросе (обычно следующем). Каждое сообщение помечается определенным «уровнем», который определяет его приоритет (например, «информация», «предупреждение» или «ошибка»).

Включение сообщений

Сообщения реализуются через класс промежуточного программного обеспечения и соответствующий контекстный процессор.

Файл settings.py по умолчанию, созданный django-admin startproject, уже содержит все настройки, необходимые для включения функциональности сообщений:

  • 'django.contrib.messages' находится в INSTALLED_APPS.

  • MIDDLEWARE содержит 'django.contrib.sessions.middleware.SessionMiddleware' и 'django.contrib.messages.middleware.MessageMiddleware'.

    Базовая часть хранилища по умолчанию <message-storage-backends>` использует сессии. Вот почему SessionMiddleware должен быть включен и появляться перед MessageMiddleware в MIDDLEWARE.

  • Опция 'context_processors' бэкенда DjangoTemplates, определенная в вашем параметре TEMPLATES, содержит 'django.contrib.messages.context_processors.messages'.

Если вы не хотите использовать сообщения, вы можете удалить 'django.contrib.messages'` из вашего :setting:`INSTALLED_APPS`, строку ``MessageMiddleware из MIDDLEWARE и контекстного процессора messages из TEMPLATES.

Настройка механизма сообщений

Серверные части хранилища

Платформа сообщений может использовать разные серверные части для хранения временных сообщений.

Django предоставляет три встроенных класса хранения в django.contrib.messages:

class storage.session.SessionStorage

Этот класс хранит все сообщения внутри сеанса запроса. Поэтому для этого требуется приложение Django contrib.sessions.

class storage.cookie.CookieStorage

Этот класс хранит данные сообщения в файле cookie (подписанном секретным хешем для предотвращения манипуляций) для сохранения уведомлений между запросами. Старые сообщения удаляются, если размер данных cookie превышает 2048 байт.

class storage.fallback.FallbackStorage

Этот класс сначала использует CookieStorage и возвращается к использованию SessionStorage для сообщений, которые не могут поместиться в один файл cookie. Для этого также требуется приложение Django contrib.sessions.

Такое поведение позволяет избежать записи в сеанс, когда это возможно. В общем случае он должен обеспечивать наилучшую производительность.

FallbackStorage — класс хранилища по умолчанию. Если он не соответствует вашим потребностям, вы можете выбрать другой класс хранилища, задав для MESSAGE_STORAGE полный путь импорта, например:

MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'
class storage.base.BaseStorage

Чтобы написать свой собственный класс хранилища, создайте подкласс класса BaseStorage в django.contrib.messages.storage.base и реализуйте методы _get и _store.

Уровни сообщений

Платформа сообщений основана на архитектуре настраиваемого уровня, аналогичной архитектуре модуля ведения журнала Python. Уровни сообщений позволяют группировать сообщения по типу, чтобы их можно было фильтровать или по-разному отображать в представлениях и шаблонах.

Встроенные уровни, которые можно импортировать напрямую из django.contrib.messages:

Постоянный

Цель

DEBUG

Сообщения, связанные с разработкой, которые будут игнорироваться (или удаляться) при производственном развертывании.

ИНФО

Информационные сообщения для пользователя

УСПЕХ

Действие было успешным, например. «Ваш профиль успешно обновлен»

ВНИМАНИЕ

Сбой не произошел, но может быть неизбежным

ОШИБКА

Действие было не успешным или произошел какой-либо другой сбой

Параметр MESSAGE_LEVEL можно использовать для изменения минимального записываемого уровня (или его можно изменять по запросу). Попытки добавить сообщения уровня ниже этого будут игнорироваться.

Теги сообщений

Теги сообщений представляют собой строковое представление уровня сообщения плюс любые дополнительные теги, которые были добавлены непосредственно в представлении (дополнительную информацию см. в разделе «Добавление дополнительных тегов сообщений» ниже). Теги хранятся в виде строки и разделяются пробелами. Обычно теги сообщений используются как классы CSS для настройки стиля сообщения в зависимости от типа сообщения. По умолчанию каждый уровень имеет один тег, который представляет собой строчную версию собственной константы:

Константа уровня

Ярлык

DEBUG

debug

ИНФО

информация

УСПЕХ

успех

ВНИМАНИЕ

предупреждение

ОШИБКА

ошибка

Чтобы изменить теги по умолчанию для уровня сообщения (встроенного или пользовательского), установите для параметра MESSAGE_TAGS словарь, содержащий уровни, которые вы хотите изменить. Поскольку это расширяет теги по умолчанию, вам нужно предоставить теги только для тех уровней, которые вы хотите переопределить:

from django.contrib.messages import constants as messages
MESSAGE_TAGS = {
    messages.INFO: '',
    50: 'critical',
}

Использование сообщений в представлениях и шаблонах

add_message(request, level, 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(request)

In your template, use something like:

{% if messages %}
<ul class="messages">
    {% for message in messages %}
    <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
    {% endfor %}
</ul>
{% endif %}

Если вы используете контекстный процессор, ваш шаблон должен отображаться с помощью RequestContext. В противном случае убедитесь, что сообщения доступны для контекста шаблона.

Даже если вы знаете, что есть только одно сообщение, вам все равно следует перебирать последовательность «сообщений», потому что в противном случае хранилище сообщений не будет очищено для следующего запроса.

The context processor also provides a DEFAULT_MESSAGE_LEVELS variable which is a mapping of the message level names to their numeric value:

{% 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() вернет экземпляр настроенного бэкэнда хранилища.

Класс Сообщение

class storage.base.Message

Когда вы перебираете список сообщений в шаблоне, вы получаете экземпляры класса Message. У них есть всего несколько атрибутов:

  • message: фактический текст сообщения.

  • уровень: целое число, описывающее тип сообщения (см. раздел ``уровни сообщений`_ выше).

  • 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

ИНФО

20

УСПЕХ

25

ВНИМАНИЕ

30

ОШИБКА

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_silily=True в любой из методов add_message. Например:

messages.add_message(
    request, messages.SUCCESS, 'Profile details updated.',
    fail_silently=True,
)
messages.info(request, 'Hello world.', fail_silently=True)

Примечание

Установка fail_silly=True только скрывает MessageFailure, который в противном случае мог бы произойти, если платформа сообщений отключена и кто-то попытается использовать один из методов add_message. Он не скрывает сбои, которые могут возникнуть по другим причинам.

Добавление сообщений в представлениях на основе классов

class 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"

Очищенные данные из формы доступны для строковой интерполяции с использованием синтаксиса %(имя_поля)s. Для ModelForms, если вам нужен доступ к полям из сохраненного объекта, переопределите метод get_success_message().

Пример view.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, где каждое окно/вкладка будет иметь свой собственный контекст просмотра.

Настройки

Несколько settings дают вам контроль над поведением сообщений:

Для серверов, использующих файлы cookie, настройки файла cookie берутся из настроек файла cookie сеанса:

Back to Top