Pull to refresh

Всем по сообщению

Reading time6 min
Views15K
Original author: Jeff Croft
В сегодняшних веб-приложениях часто требуется выдать посетителю некоторое оповещение. Будь то «Ваш комментарий сохранён и ожидает модерации» или же «Благодарим за проявленный интерес, мы обязательно вышлем Вам приглашение, как только откроемся», эти небольшие сообщения появляются то тут, то там постоянно, так что весьма здорово иметь удобный интерфейс для отображения их пользователю.

Идущее в поставке с Django приложение аутентификации и авторизации (django.contrib.auth) всегда включало базовый функционал для отображения всплывающих сообщений пользователю, но он имел несколько досадных недостатков. В Django 1.2 же теперь есть совершенно новый фреймворк для таких сообщений, написанный в первую очередь Тобаясом Макналти (Tobias McNulty).


Так что же было не так со старым способом?


Поскольку старая система сообщений является частью django.contrib.auth, вы должны подключить это приложение, чтобы воспользоваться малой его частью, отвечающей за оповещения. Но бывает, что вам не нужны аутентификация и авторизация, но нужны эти маленькие сообщения. Или, возможно, вы используете своё собственное приложение аутентификации. Или же, наоборот, вы используете django.contrib.auth, но вам не нужны сообщения. В Django 1.2 у вас наконец появилась возможность для всего этого.

Кроме того, старая система хранит сообщения в базе данных. И хоть это и нормально для многих проектов, всё-таки это означает, что каждый просмотр любой странички сопровождается дополнительным запросом к БД. А он попросту не нужен в большинстве случаев. В Django 1.2 появилась возможность хранить сообщения вне базы данных для небольшого повышения производительности.

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

Наконец, система оповещений в Django 1.1 жёстко привязывает каждое сообщение к конкретному пользователю, что означает, что вы не можете показывать такие сообщения анонимным пользователям. В Django 1.2 появилась и возможность показывать оповещения вне зависимости от того, залогинен пользователь или нет.


Итак, приступим.


Новая система уже подключена по умолчанию, если вы создаёте проект при помощи django-admin.py startproject. Если же у вас уже есть старый проект, или вы создали проект каким-либо другим способом, включить систему очень просто. Всего три шага:
  1. Добавьте 'django.contrib.messages.middleware.MessageMiddleware' в список MIDDLEWARE_CLASSES в файле настроек.
  2. Добавьте 'django.contrib.messages.context_processors.messages' в список TEMPLATE_CONTEXT_PROCESSORS в файле настроек.
  3. Добавьте 'django.contrib.messages' в список INSTALLED_APPS всё в том же файле настроек.

Добавление оповещений


Добавление оповещений пользователям в новом фреймворке также элементарно, особенно если вам достаточно одного из пяти предопределённых типов сообщений (DEBUG, INFO, SUCCESS, WARNING, ERROR — об этом чуть позже).

Итак, что же вам нужно сделать:
  1. from django.contrib import messages
  2. messages.success(request, "Skadoosh! You've updated your profile!")
Точно так же и для других типов сообщений:
  1. messages.info(request, 'Yo! There are new comments on your photo!')
  2. messages.error(request, 'Doh! Something went wrong.')
  3. messages.debug(request, 'Bam! %s objects were modified.' % modified_count)
  4. messages.warning(request, 'Uh-oh. Your account expires in %s days.' % expiration_days)
Поскольку сообщения прикрепляются к объекту request, вам понадобится доступ к нему, но он у вас уже есть во всех вьюшках.

Если вы переходите со старой версии, вам понадобится выполнить всего два несложных пункта:
  1. Во всех файлах views.py, где имеется создание оповещений, добавьте в начале следующую строку:
    from django.contrib import messages
  2. Замените везде
    request.user.message_set.create(message=message)
    на вызов одного из методов нового API, например
    messages.error(request, message)

Отображение сообщений


Для вывода сообщений в шаблоне используйте нечто вроде следующих строк:
  1. {% if messages %}
  2.     <ul class="messages">
  3.     {% for message in messages %}
  4.         <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>
  5.             {{ message }}
  6.         </li>
  7.     {% endfor %}
  8.     </ul>
  9. {% endif %}
Как правило имеет смысл поместить эти строки в ваш базовый шаблон, так чтобы все шаблоны, наследующие его, отображали оповещения.

Код практически идентичен тому, что вы уже использовали в Django 1.1, но вы должны были заметить новое свойство tags. Django 1.2 даёт каждому оповещению тип со строковым представлением для использования в шаблонах. В данном случае мы выводим это значение в качестве имени CSS класса, которое может быть использовано для индивидуальной стилизации различных типов сообщений, например:
  1. .messages li.error { background-color: red; }
  2. .messages li.success { background-color: green; }
Если вы просто хотите показывать пользователю сообщения, можете дальше не читать. На самом деле больше ничего и не надо. Всё легко и просто.


Механизмы хранения сообщений


Django предоставляет несколько бэкендов для хранения сообщений, и очень легко вы можете создать свой собственный. LegacyFallbackStorage используется по умолчанию и подойдёт для большинства проектов, однако, есть несколько причин, по которым вы захотите сменить бэкенд:
  • django.contrib.messages.storage.session.SessionStorage. Этот бэкенд хранит все сообщения в сессии. Таким образом, требуется подключить приложение django.contrib.sessions (скорее всего оно уже активировано в вашем проекте, т.к. оно используется по умолчанию). Поскольку сессии по умолчанию хранятся в базе данных, использование этого бэкенда всё ещё требует запроса к БД при обращении к сообщениям (например, при вызове {% if messages %} в шаблоне).
  • django.contrib.messages.storage.cookie.CookieStorage хранит сообщения в куках. Таким образом, запрос к базе не требуется, что влечёт большую производительность. Однако, имеется один недостаток: максимальная длина куки — 4096 байт, так что сообщения длиннее 4 КБ доставлены не будут.
  • django.contrib.messages.storage.fallback.FallbackStorage: этот механизм сперва использует CookieStorage, но в случае, когда текст не помещается в куку, обращается к SessionStorage.
  • django.contrib.messages.storage.user_messages.LegacyFallbackStorage. Предоставлен для обратной совместимости с Django 1.1 и более ранними версиями. Работает точно так же, как FallbackStorage, но также получает сообщения из старой системы оповещений — django.contrib.auth. Однако, как и сама система из django.contrib.auth, этот механизм объявлен устаревшим и будет убран из Django 1.4. Пока этот механизм используется по умолчанию, но как только его уберут, на его место встанет FallbackStorage.

Типы сообщений и тэги


Как было упомянуто ранее, Django предоставляет 5 встроенных типов сообщений. Каждый тип — это целое число. Вы без проблем можете расширить или изменить существующие типы. По умолчанию мы имеем:
  • DEBUG: 10
  • INFO: 20
  • SUCCESS: 25
  • WARNING: 30
  • ERROR: 40
Чтобы добавить свой собственный тип, объявите константу и вызовите метод add_message() для создания сообщения нового типа:
  1. CRITICAL = 50
  2. messages.add_message(request, CRITICAL, 'OH NOES! A critical error occured.')
Конечно, вы захотите использовать эту информацию в HTML и CSS, так что вам потребуется добавить настройку MESSAGE_TAGS в ваш файл settings.py, чтобы задать строковое представление вашему новому типу сообщений:
  1. MESSAGE_TAGS = {50: 'critical'}

В заключение


Новая система сообщений, включенная в Django 1.2, — это не очень сложная часть фреймворка, но она предоставляет функционал, без которого нельзя представить современное веб-приложение, и делает это очень элегантно и просто. Кроме того, она полностью совместима с предыдушими версиями, так что вам не надо беспокоиться о том, что старый код или сторонние приложения сломаются после перехода на 1.2. Но не забывайте, что прослойка совместимости будет удалена в 1.4, запланированной где-то на вторую половину 2027-го года.

Шутка. Наслаждайтесь Django 1.2! Это действительно классное обновление нашего любимого фреймворка.

--
Перевод подготовлен в Vim.
Tags:
Hubs:
+54
Comments12

Articles