Spec-Zone.ru › Django 2.0

Система сообщений

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

Для этого 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:

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

Встроенные уровни, которые можно импортировать из 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(request, level, message, extra_tags='', fail_silently=False) [source]

Добавление сообщения

Для добавления сообщения вызовите:

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) [source]

В вашем шаблоне используйте что-то вроде:

{% 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

class 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. Это не скрывает ошибки, которые могут возникнуть по другим причинам.

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

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"

Очищенные данные из 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 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

Поведение параллельных запросов

Из-за того, как работают куки (и, следовательно, сессии), поведение любых бэкэндов, использующих куки или сессии, не определено, когда один и тот же клиент выполняет несколько запросов, которые устанавливают или получают сообщения параллельно. Например, если клиент инициирует запрос, который создаёт сообщение в одном окне (или вкладке), а затем другой, который извлекает любые неитерированные сообщения в другом окне, прежде чем первое окно перенаправится, сообщение может появиться во втором окне вместо первого окна, где оно ожидается.

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

Настройки

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

  • MESSAGE_LEVEL
  • MESSAGE_STORAGE
  • MESSAGE_TAGS

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

  • SESSION_COOKIE_DOMAIN
  • SESSION_COOKIE_SECURE
  • SESSION_COOKIE_HTTPONLY

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/2.0/ref/contrib/messages/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API