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

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

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

класс storage.cookie.CookieStorage

Этот класс хранит данные сообщения в файле 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, где каждое окно / вкладка имеет свой собственный контекст просмотра.

Настройки

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

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

Copyright ©2020 All rights reserved