在 web 应用程序中,通常需要在处理表单或其他类型的用户输入之后,向用户显示一个通知消息(也称为 flash message)。对于这个功能,Django 提供基于 Cookie 和会话的消息,无论是匿名用户还是认证的用户。消息框架允许临时将消息存储在请求中,并在下一个请求中提取它们并显示。每个消息都带有一个特定 level 标签,表示其优先级。
启用消息框架
消息框架的实现通过一个中间件类和对应的上下文处理器。django-admin startproject 命令创建的默认 settings.py 已经包含启用消息框架功能需要的所有的设置:
INSTALLED_APPS
- django.contrib.messages
MIDDLEWARE
- django.contrib.sessions.middleware.SessionMiddleware
- django.contrib.messages.middleware.MessageMiddleware
默认的后端存储依赖 sessions。所以中间件中必须启用 SessionMiddleware 并出现在 MessageMiddleware 之前。
TEMPLATES
- context_processors 选项包含 django.contrib.messages.context_processors.messages
配置消息引擎
1. 存储后端
消息框架可以使用不同的后端存储临时消息。
Django 在 django.contrib.messages 中提供了三个内置的存储类:
(1)class storage.session.SessionStorage
该类存储请求会话中的所有消息。因此它需要启用 django.contrib.sessions 应用。
(2)class storage.cookie.CookieStorage
该类将消息数据存储在 cookie 中,以便在请求之间持久化通知。如果 cookie 数据大小超过 2048 字节,则删除旧消息。
(3)class storage.fallback.FallbackStorage
FallbackStorage 是默认的存储类。这个类首先使用 CookieStorage,然后使用 SessionStorage 来存储不能放入单个 cookie 的消息。
这种行为尽量避免向会话写入内容。在一般情况下提供最好的性能。
2. 消息等级
消息框架可配置消息级别。消息级别按类型对消息进行分组,以便在视图和模板中以不同的方式过滤或显示消息。
django.contrib.messages 内置消息级别:DEBUG,INFO,SUCCESS,WARNING,ERROR。
MESSAGE_LEVEL 设置可以用来改变记录的最小级别(还可以在每个请求中修改),小于这个级别的消息将被忽略。
消息标签
消息标签是消息级别的字符串表示形式,加上直接在视图中添加的任何额外标记。标记存储在字符串中,并由空格分隔。通常,消息标记被用作 CSS 类,以根据消息类型定制消息样式。
默认情况下,每个消息级别都有一个消息标签(messages.tags):debug,info,success,warning,error。
Constant | Level | Tag | Purpose |
DEBUG | 10 | debug | 与开发相关的消息 |
INFO | 20 | info | 为用户提供的消息 |
SUCCESS | 25 | success | 操作成功的消息 |
WARNING | 30 | warning | 未失败的告警消息 |
ERROR | 40 | error | 操作失败的消息 |
在视图和模板中使用消息
添加消息
要添加消息,使用 message.add_message() 方法:
1 from django.contrib import messages 2 3 messages.add_message(request, level, message, extra_tags='', fail_silently=False)
一些快捷方式提供了一种标准的方式来添加带有常用标记的消息(通常表示为消息的HTML类):
1 messages.debug(request, '%s SQL statements were executed.' % count) 2 messages.info(request, 'Three credits remain in your account.') 3 messages.success(request, 'Profile details updated.') 4 messages.warning(request, 'Your account expires in three days.') 5 messages.error(request, 'Document deleted.')
显示消息
{% if messages %} <ul class="messages"> {% for message in messages %} <li {% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li> {% endfor %} </ul> {% endif %}
即使只有一条消息,仍然应该遍历消息序列,否则消息存储将不会为下一个请求清除。