Spec-Zone.ru › Django 1.8

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

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

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

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

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

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

  • 'django.contrib.messages' находится в INSTALLED_APPS.
  • MIDDLEWARE_CLASSES содержит 'django.contrib.sessions.middleware.SessionMiddleware' и 'django.contrib.messages.middleware.MessageMiddleware'.

    По умолчанию хранилище данных использует сессии. Поэтому SessionMiddleware должен быть включен и находиться перед MessageMiddleware в MIDDLEWARE_CLASSES.

  • Опция 'context_processors' DjangoTemplates хранилища, определённого в вашей настройке TEMPLATES, содержит 'django.contrib.messages.context_processors.messages'.

Если вы не хотите использовать систему сообщений, вы можете удалить 'django.contrib.messages' из вашей INSTALLED_APPS, строку MessageMiddleware из MIDDLEWARE_CLASSES и процессор контекста 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/1.8/ref/contrib/messages/

Spec-Zone.ru

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