消息框架

在Web应用程序中,通常需要在处理表单或其他类型的用户输入后向用户显示一次性通知消息(也称为“闪存消息”)。

为此,Django为匿名用户和认证用户提供了基于cookie和会话的消息传递的完全支持。消息框架允许您在一个请求中临时存储消息,并检索它们以在随后的请求(通常是下一个请求)中显示。每条消息都用特定的 level 它决定了它的优先级(例如, infowarningerror

启用消息

消息通过 middleware 类和对应的 context processor .

默认值 settings.py 创建的 django-admin startproject 已包含启用邮件功能所需的所有设置:

  • 'django.contrib.messages' 是在 INSTALLED_APPS .

  • MIDDLEWARE 包含 'django.contrib.sessions.middleware.SessionMiddleware''django.contrib.messages.middleware.MessageMiddleware' .

    默认值 storage backend 依赖于 sessions . 这就是为什么 SessionMiddleware 必须启用并出现在 MessageMiddleware 在里面 MIDDLEWARE .

  • 这个 'context_processors' 选择权 DjangoTemplates 后端在您的 TEMPLATES 设置包含 'django.contrib.messages.context_processors.messages' .

如果不想使用邮件,可以删除 'django.contrib.messages' 从你 INSTALLED_APPS , the MessageMiddleware 线从 MIDDLEWAREmessages 上下文处理器来自 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日志记录模块的可配置级别体系结构。消息级别允许您按类型对消息分组,以便在视图和模板中对其进行筛选或以不同的方式显示。

可从中导入的内置级别 django.contrib.messages 直接是:

常数

目的

DEBUG

将在生产部署中被忽略(或删除)的与开发相关的消息

INFO

用户的信息性消息

SUCCESS

操作成功,例如“您的配置文件更新成功”

WARNING

未发生故障,但可能即将发生。

ERROR

一个行动是 not 成功或发生其他故障

这个 MESSAGE_LEVEL 设置可用于更改最小记录水平(或 changed per request )尝试添加低于此级别的消息将被忽略。

消息标签

消息标记是消息级别的字符串表示,加上直接添加到视图中的任何额外标记(请参见 Adding extra message tags 详情请参见下文)。标记存储在字符串中,并用空格分隔。通常,消息标记用作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)[源代码]

添加消息

若要添加消息,请致电:

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)[源代码]

In your template ,请使用类似以下内容:

{% 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 Message[源代码]

当您遍历模板中的消息列表时,您得到的是 Message 班级。它们只有几个属性:

  • message :消息的实际文本。

  • level :描述消息类型的整数(请参见 message levels 以上章节)。

  • tags :组合所有邮件标签的字符串 (extra_tagslevel_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 设置。

备注

如果要创建可重用的应用程序,建议仅使用内置的 message levels 不依赖任何自定义级别。

更改每个请求的最低记录级别

可通过以下方式设置每个请求的最低记录级别: 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)

有关最低记录级别如何工作的详细信息,请参见 Message levels 上面。

添加额外的邮件标签

为了更直接地控制消息标记,您可以选择向任何添加方法提供包含额外标记的字符串:

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 从用于字符串格式设置的表单中清除的数据

示例视图.py ::

from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.edit import CreateView
from myapp.models import Author


class AuthorCreateView(SuccessMessageMixin, CreateView):
    model = Author
    success_url = "/success/"
    success_message = "%(name)s was created successfully"

从中清除的数据 form 可用于字符串插值,使用 %(field_name)s 语法。对于模型窗体,如果需要从保存的 object 覆盖 get_success_message() 方法。

ModelForms的Views.py示例 ::

from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.edit import CreateView
from myapp.models import ComplicatedModel


class ComplicatedCreateView(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中,这将成为一个非问题,在HTML5中,每个窗口/选项卡都有自己的浏览上下文。

设置

少许 settings 允许您控制消息行为:

对于使用cookie的后端,cookie的设置取自会话cookie设置:

测试

New in Django 5.0.

此模块提供定制的测试断言方法,用于测试附加到 HttpResponse

要从此断言中获益,请添加 MessagesTestMixin 到类层次结构::

from django.contrib.messages.test import MessagesTestMixin
from django.test import TestCase


class MsgTestCase(MessagesTestMixin, TestCase):
    pass

然后,从 MsgTestCase 在你的测试中。

MessagesTestMixin.assertMessages(response, expected_messages, ordered=True)[源代码]

断言 messages 添加到 response 火柴 expected_messages

expected_messages 是一份 Message 物体。

默认情况下,比较依赖于顺序。可以通过设置 ordered 参数为 False