“Django/docs/3.0.x/ref/contrib/messages”的版本间差异
(autoload) |
小 (Page commit) |
||
第1行: | 第1行: | ||
+ | {{DISPLAYTITLE:消息框架 — Django 文档}} | ||
<div id="module-django.contrib.messages" class="section"> | <div id="module-django.contrib.messages" class="section"> | ||
<span id="the-messages-framework"></span> | <span id="the-messages-framework"></span> | ||
− | = | + | = 消息框架 = |
− | + | 在 Web 应用程序中,在处理表单或某些其他类型的用户输入后,您需要向用户显示一次性通知消息(也称为“闪现消息”),这很常见。 | |
− | |||
− | |||
− | + | 为此,Django 为匿名和经过身份验证的用户提供对基于 cookie 和会话的消息传递的全面支持。 消息框架允许您在一个请求中临时存储消息并检索它们以在后续请求(通常是下一个请求)中显示。 每条消息都标有确定其优先级的特定 <code>level</code>(例如,<code>info</code>、<code>warning</code> 或 <code>error</code>)。 | |
− | |||
− | |||
− | |||
− | |||
− | <code>warning</code> | ||
<div id="enabling-messages" class="section"> | <div id="enabling-messages" class="section"> | ||
− | == | + | == 启用消息 == |
− | + | 消息通过 [[../../middleware|中间件]] 类和相应的 [[../../templates/api|上下文处理器]] 实现。 | |
− | |||
− | + | <code>django-admin startproject</code> 创建的默认 <code>settings.py</code> 已经包含启用消息功能所需的所有设置: | |
− | |||
<ul> | <ul> | ||
− | <li><p><code>'django.contrib.messages'</code> | + | <li><p><code>'django.contrib.messages'</code> 在 [[#id1|:setting:`INSTALLED_APPS`]] 中。</p></li> |
− | <li><p>[[ | + | <li><p>[[#id3|:setting:`MIDDLEWARE`]] 包含 <code>'django.contrib.sessions.middleware.SessionMiddleware'</code> 和 <code>'django.contrib.messages.middleware.MessageMiddleware'</code>。</p> |
− | <code>'django.contrib.sessions.middleware.SessionMiddleware'</code> | + | <p>默认的 [[#message-storage-backends|存储后端]] 依赖于 [[../../../topics/http/sessions|会话]] 。 这就是为什么 <code>SessionMiddleware</code> 必须启用并出现在 [[#id5|:setting:`MIDDLEWARE`]] 中的 <code>MessageMiddleware</code> 之前。</p></li> |
− | <code>'django.contrib.messages.middleware.MessageMiddleware'</code> | + | <li><p>[[#id7|:setting:`TEMPLATES`]] 设置中定义的 <code>DjangoTemplates</code> 后端的 <code>'context_processors'</code> 选项包含 <code>'django.contrib.messages.context_processors.messages'</code>。</p></li></ul> |
− | <p> | ||
− | [[../../../topics/http/sessions| | ||
− | |||
− | [[ | ||
− | <li><p> | ||
− | |||
− | <code>'django.contrib.messages.context_processors.messages'</code> | ||
− | + | 如果您不想使用消息,可以从 [[#id9|:setting:`INSTALLED_APPS`]]、[[#id11|:setting:` 中的 <code>MessageMiddleware</code> 行中删除 <code>'django.contrib.messages'</code> MIDDLEWARE`]],以及来自 [[#id13|:setting:`TEMPLATES`]] 的 <code>messages</code> 上下文处理器。 | |
− | |||
− | |||
− | |||
第47行: | 第29行: | ||
<div id="configuring-the-message-engine" class="section"> | <div id="configuring-the-message-engine" class="section"> | ||
− | == | + | == 配置消息引擎 == |
<div id="storage-backends" class="section"> | <div id="storage-backends" class="section"> | ||
<span id="message-storage-backends"></span> | <span id="message-storage-backends"></span> | ||
− | === | + | === 存储后端 === |
− | + | 消息框架可以使用不同的后端来存储临时消息。 | |
− | Django | + | Django 在 [[#module-django.contrib.messages|django.contrib.messages]] 中提供了三个内置的存储类: |
− | [[#module-django.contrib.messages| | ||
− | ; ''class'' < | + | ; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">storage.session.</span></span><span class="sig-name descname"><span class="pre">SessionStorage</span></span> |
− | : | + | : 此类存储请求会话中的所有消息。 因此它需要 Django 的 <code>contrib.sessions</code> 应用程序。 |
− | ; ''class'' < | + | ; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">storage.cookie.</span></span><span class="sig-name descname"><span class="pre">CookieStorage</span></span> |
− | : | + | : 此类将消息数据存储在 cookie 中(使用秘密哈希签名以防止操纵)以跨请求保留通知。 如果 cookie 数据大小超过 2048 字节,旧消息将被丢弃。 |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">storage.fallback.</span></span><span class="sig-name descname"><span class="pre">FallbackStorage</span></span></dt> |
− | <dd><p> | + | <dd><p>这个类首先使用 <code>CookieStorage</code>,然后回退到使用 <code>SessionStorage</code> 来处理无法放入单个 cookie 的消息。 它还需要 Django 的 <code>contrib.sessions</code> 应用程序。</p> |
− | <code>SessionStorage</code> | + | <p>此行为尽可能避免写入会话。 它应该在一般情况下提供最佳性能。</p></dd></dl> |
− | |||
− | <p> | ||
− | |||
− | [[#django.contrib.messages.storage.fallback.FallbackStorage| | + | [[#django.contrib.messages.storage.fallback.FallbackStorage|FallbackStorage]] 是默认的存储类。 如果它不适合您的需求,您可以通过将 [[#id15|:setting:`MESSAGE_STORAGE`]] 设置为其完整导入路径来选择其他存储类,例如: |
− | |||
− | |||
− | |||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第82行: | 第57行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | ; ''class'' < | + | ; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">storage.base.</span></span><span class="sig-name descname"><span class="pre">BaseStorage</span></span> |
: | : | ||
− | + | 要编写自己的存储类,请在 <code>django.contrib.messages.storage.base</code> 中继承 <code>BaseStorage</code> 类并实现 <code>_get</code> 和 <code>_store</code> 方法。 | |
− | <code>django.contrib.messages.storage.base</code> | ||
− | <code>_store</code> | ||
第99行: | 第72行: | ||
<span id="message-level"></span> | <span id="message-level"></span> | ||
− | === | + | === 消息级别 === |
− | + | 消息框架基于类似于 Python 日志记录模块的可配置级别架构。 消息级别允许您按类型对消息进行分组,以便它们可以在视图和模板中进行过滤或以不同方式显示。 | |
− | |||
− | |||
− | |||
− | + | 可以直接从<code>django.contrib.messages</code>中导入的内置关卡有: | |
− | |||
{| | {| | ||
− | !width="11%"| | + | !width="11%"| 常数 |
− | !width="89%"| | + | !width="89%"| 目的 |
|- | |- | ||
| <code>DEBUG</code> | | <code>DEBUG</code> | ||
− | | | + | | 在生产部署中将被忽略(或删除)的与开发相关的消息 |
|- | |- | ||
| <code>INFO</code> | | <code>INFO</code> | ||
− | | | + | | 给用户的信息性消息 |
|- | |- | ||
| <code>SUCCESS</code> | | <code>SUCCESS</code> | ||
− | | | + | | 一个动作成功,例如 “您的个人资料已成功更新” |
|- | |- | ||
| <code>WARNING</code> | | <code>WARNING</code> | ||
− | | | + | | 故障没有发生,但可能即将发生 |
|- | |- | ||
| <code>ERROR</code> | | <code>ERROR</code> | ||
− | | | + | | 操作 '''不''' 成功或发生其他一些失败 |
|} | |} | ||
− | + | [[#id17|:setting:`MESSAGE_LEVEL`]] 设置可用于更改最小记录级别(或者可以根据请求 [[#changing-the-minimum-recorded-level-per-request|更改]] )。 尝试添加低于此级别的消息将被忽略。 | |
− | |||
− | |||
第137行: | 第104行: | ||
<div id="message-tags" class="section"> | <div id="message-tags" class="section"> | ||
− | === | + | === 消息标签 === |
− | + | 消息标签是消息级别的字符串表示以及直接添加到视图中的任何额外标签(有关更多详细信息,请参阅下面的 [[#adding-extra-message-tags|添加额外的消息标签]] )。 标签存储在一个字符串中,并用空格分隔。 通常,消息标签用作 CSS 类来根据消息类型自定义消息样式。 默认情况下,每个级别都有一个标记,它是其自身常量的小写版本: | |
− | |||
− | [[#adding-extra-message-tags| | ||
− | |||
− | |||
− | |||
− | |||
{| | {| | ||
− | !width="56%"| | + | !width="56%"| 电平常数 |
− | !width="44%"| | + | !width="44%"| 标签 |
|- | |- | ||
| <code>DEBUG</code> | | <code>DEBUG</code> | ||
第167行: | 第128行: | ||
|} | |} | ||
− | + | 要更改消息级别的默认标签(内置或自定义),请将 [[#id19|:setting:`MESSAGE_TAGS`]] 设置设置为包含您希望更改的级别的字典。 由于这扩展了默认标签,您只需为要覆盖的级别提供标签: | |
− | |||
− | |||
− | |||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第176行: | 第134行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">from django.contrib.messages import constants as messages |
MESSAGE_TAGS = { | MESSAGE_TAGS = { | ||
messages.INFO: '', | messages.INFO: '', | ||
50: 'critical', | 50: 'critical', | ||
− | }</ | + | }</syntaxhighlight> |
</div> | </div> | ||
第191行: | 第149行: | ||
<div id="using-messages-in-views-and-templates" class="section"> | <div id="using-messages-in-views-and-templates" class="section"> | ||
− | == | + | == 在视图和模板中使用消息 == |
− | ; < | + | ; <span class="sig-name descname"><span class="pre">add_message</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">request</span></span>'', ''<span class="n"><span class="pre">level</span></span>'', ''<span class="n"><span class="pre">message</span></span>'', ''<span class="n"><span class="pre">extra_tags</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">''</span></span>'', ''<span class="n"><span class="pre">fail_silently</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span>''<span class="sig-paren">)</span> |
: | : | ||
<div id="adding-a-message" class="section"> | <div id="adding-a-message" class="section"> | ||
− | === | + | === 添加留言 === |
− | + | 要添加消息,请致电: | |
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第206行: | 第164行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">from django.contrib import messages |
− | messages.add_message(request, messages.INFO, 'Hello world.')</ | + | messages.add_message(request, messages.INFO, 'Hello world.')</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 一些快捷方法提供了一种标准方式来添加带有常用标签的消息(通常表示为消息的 HTML 类): | |
− | |||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第219行: | 第176行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">messages.debug(request, '%s SQL statements were executed.' % count) |
messages.info(request, 'Three credits remain in your account.') | messages.info(request, 'Three credits remain in your account.') | ||
messages.success(request, 'Profile details updated.') | messages.success(request, 'Profile details updated.') | ||
messages.warning(request, 'Your account expires in three days.') | messages.warning(request, 'Your account expires in three days.') | ||
− | messages.error(request, 'Document deleted.')</ | + | messages.error(request, 'Document deleted.')</syntaxhighlight> |
</div> | </div> | ||
第233行: | 第190行: | ||
<span id="message-displaying"></span> | <span id="message-displaying"></span> | ||
− | === | + | === 显示消息 === |
− | ; < | + | ; <span class="sig-name descname"><span class="pre">get_messages</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">request</span></span>''<span class="sig-paren">)</span> |
: | : | ||
− | ''' | + | '''在你的模板'''中,使用类似的东西: |
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第244行: | 第201行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">{% if messages %} |
− | + | <ul class="messages"> | |
{% for message in messages %} | {% for message in messages %} | ||
− | + | <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li> | |
{% endfor %} | {% endfor %} | ||
− | + | </ul> | |
− | {% endif %}</ | + | {% endif %}</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 如果您使用上下文处理器,则您的模板应使用 <code>RequestContext</code> 呈现。 否则,请确保 <code>messages</code> 可用于模板上下文。 | |
− | <code>RequestContext</code> | ||
− | |||
− | + | 即使您知道只有一条消息,您仍然应该遍历 <code>messages</code> 序列,否则消息存储将不会为下一个请求清除。 | |
− | <code>messages</code> | ||
− | |||
− | + | 上下文处理器还提供了一个 <code>DEFAULT_MESSAGE_LEVELS</code> 变量,它是消息级别名称到其数值的映射: | |
− | |||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第270行: | 第222行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">{% if messages %} |
− | + | <ul class="messages"> | |
{% for message in messages %} | {% for message in messages %} | ||
− | + | <li{% if message.tags %} class="{{ message.tags }}"{% endif %}> | |
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}Important: {% endif %} | {% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}Important: {% endif %} | ||
{{ message }} | {{ message }} | ||
− | + | </li> | |
{% endfor %} | {% endfor %} | ||
− | + | </ul> | |
− | {% endif %}</ | + | {% endif %}</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | ''' | + | '''在模板'''之外,你可以使用[[#django.contrib.messages.get_messages|get_messages()]]: |
− | [[#django.contrib.messages.get_messages| | ||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第291行: | 第242行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">from django.contrib.messages import get_messages |
storage = get_messages(request) | storage = get_messages(request) | ||
for message in storage: | for message in storage: | ||
− | do_something_with_the_message(message)</ | + | do_something_with_the_message(message)</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 例如,您可以获取所有消息以在 [[../../../topics/class-based-views/mixins#jsonresponsemixin-example|JSONResponseMixin]] 而不是 [[../../class-based-views/mixins-simple#django.views.generic.base|TemplateResponseMixin]] 中返回它们。 | |
− | [[../../../topics/class-based-views/mixins#jsonresponsemixin-example| | ||
− | [[../../class-based-views/mixins-simple#django.views.generic.base| | ||
− | [[#django.contrib.messages.get_messages| | + | [[#django.contrib.messages.get_messages|get_messages()]] 将返回配置的存储后端的实例。 |
− | |||
第311行: | 第259行: | ||
<div id="the-message-class" class="section"> | <div id="the-message-class" class="section"> | ||
− | === | + | === Message 类 === |
− | ; ''class'' < | + | ; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">storage.base.</span></span><span class="sig-name descname"><span class="pre">Message</span></span> |
− | : | + | : 当您遍历模板中的消息列表时,您得到的是 <code>Message</code> 类的实例。 它们只有几个属性: |
− | ;* <code>message</code> | + | ;* <code>message</code>:消息的实际文本。 |
− | ;* <code>level</code> | + | ;* <code>level</code>:描述消息类型的整数(请参阅上面的 [[#message-levels|消息级别]] 部分)。 |
− | ;* <code>tags</code> | + | ;* <code>tags</code>:由空格分隔的所有消息标签(<code>extra_tags</code> 和 <code>level_tag</code>)组合而成的字符串。 |
− | ;* <code>extra_tags</code> | + | ;* <code>extra_tags</code>:包含此消息的自定义标签的字符串,以空格分隔。 默认为空。 |
− | ;* <code>level_tag</code> | + | ;* <code>level_tag</code>:级别的字符串表示。 默认情况下,它是关联常量名称的小写版本,但如果需要,可以使用 [[#id21|:setting:`MESSAGE_TAGS`]] 设置进行更改。 |
第325行: | 第273行: | ||
<div id="creating-custom-message-levels" class="section"> | <div id="creating-custom-message-levels" class="section"> | ||
− | === | + | === 创建自定义消息级别 === |
− | + | 消息级别只不过是整数,因此您可以定义自己的级别常量并使用它们来创建更多定制的用户反馈,例如: | |
− | |||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第334行: | 第281行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">CRITICAL = 50 |
def my_view(request): | def my_view(request): | ||
− | messages.add_message(request, CRITICAL, 'A serious error occurred.')</ | + | messages.add_message(request, CRITICAL, 'A serious error occurred.')</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 创建自定义消息级别时,您应该小心避免使现有级别过载。 内置级别的值是: | |
− | |||
{| | {| | ||
− | !width="74%"| | + | !width="74%"| 电平常数 |
− | !width="26%"| | + | !width="26%"| 价值 |
|- | |- | ||
| <code>DEBUG</code> | | <code>DEBUG</code> | ||
第365行: | 第311行: | ||
|} | |} | ||
− | + | 如果您需要在 HTML 或 CSS 中识别自定义级别,则需要通过 [[#id23|:setting:`MESSAGE_TAGS`]] 设置提供映射。 | |
− | |||
<div class="admonition note"> | <div class="admonition note"> | ||
− | + | 笔记 | |
− | + | 如果您正在创建可重用的应用程序,建议仅使用内置的 [[#message-levels|消息级别]] ,不要依赖任何自定义级别。 | |
− | |||
第381行: | 第325行: | ||
<div id="changing-the-minimum-recorded-level-per-request" class="section"> | <div id="changing-the-minimum-recorded-level-per-request" class="section"> | ||
− | === | + | === 更改每个请求的最低记录级别 === |
− | + | 可以通过 <code>set_level</code> 方法为每个请求设置最低记录级别: | |
− | |||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第390行: | 第333行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">from django.contrib import messages |
# Change the messages level to ensure the debug message is added. | # Change the messages level to ensure the debug message is added. | ||
第402行: | 第345行: | ||
# Set the messages level back to default. | # Set the messages level back to default. | ||
− | messages.set_level(request, None)</ | + | messages.set_level(request, None)</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 类似地,可以通过 <code>get_level</code> 检索当前有效级别: | |
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第413行: | 第356行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">from django.contrib import messages |
− | current_level = messages.get_level(request)</ | + | current_level = messages.get_level(request)</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 有关最低记录级别如何运作的更多信息,请参阅上面的 [[#message-levels|消息级别]] 。 | |
− | [[#message-levels| | ||
第426行: | 第368行: | ||
<div id="adding-extra-message-tags" class="section"> | <div id="adding-extra-message-tags" class="section"> | ||
− | === | + | === 添加额外的消息标签 === |
− | + | 为了更直接地控制消息标签,您可以选择向任何添加方法提供一个包含额外标签的字符串: | |
− | |||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第435行: | 第376行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">messages.add_message(request, messages.INFO, 'Over 9000!', extra_tags='dragonball') |
− | messages.error(request, 'Email box full', extra_tags='email')</ | + | messages.error(request, 'Email box full', extra_tags='email')</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 在该级别的默认标签之前添加额外的标签,并以空格分隔。 | |
− | |||
第448行: | 第388行: | ||
<div id="failing-silently-when-the-message-framework-is-disabled" class="section"> | <div id="failing-silently-when-the-message-framework-is-disabled" class="section"> | ||
− | === | + | === 禁用消息框架时静默失败 === |
− | + | 如果您正在编写一个可重用的应用程序(或其他代码段)并希望包含消息传递功能,但又不想要求您的用户启用它(如果他们不想启用它),您可以传递一个额外的关键字参数 [ X220X] 到 <code>add_message</code> 方法系列中的任何一个。 例如: | |
− | |||
− | |||
− | |||
− | |||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第460行: | 第396行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">messages.add_message( |
request, messages.SUCCESS, 'Profile details updated.', | request, messages.SUCCESS, 'Profile details updated.', | ||
fail_silently=True, | fail_silently=True, | ||
) | ) | ||
− | messages.info(request, 'Hello world.', fail_silently=True)</ | + | messages.info(request, 'Hello world.', fail_silently=True)</syntaxhighlight> |
</div> | </div> | ||
第471行: | 第407行: | ||
<div class="admonition note"> | <div class="admonition note"> | ||
− | + | 笔记 | |
− | + | 设置 <code>fail_silently=True</code> 只会隐藏 <code>MessageFailure</code>,否则会在消息框架禁用并尝试使用 <code>add_message</code> 系列方法之一时发生。 它不会隐藏由于其他原因可能发生的故障。 | |
− | |||
− | |||
− | |||
第484行: | 第417行: | ||
<div id="adding-messages-in-class-based-views" class="section"> | <div id="adding-messages-in-class-based-views" class="section"> | ||
− | === | + | === 在基于类的视图中添加消息 === |
− | ; ''class'' < | + | ; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">views.</span></span><span class="sig-name descname"><span class="pre">SuccessMessageMixin</span></span> |
− | : | + | : 向基于 [[../../class-based-views/generic-editing#django.views.generic.edit|FormView]] 的类添加成功消息属性 |
− | ;; < | + | ;; <span class="sig-name descname"><span class="pre">get_success_message</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">cleaned_data</span></span>''<span class="sig-paren">)</span> |
− | ;: <code>cleaned_data</code> | + | ;: <code>cleaned_data</code> 是用于字符串格式化的表单中的清理数据 |
− | ''' | + | '''示例views.py''': |
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第497行: | 第430行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">from django.contrib.messages.views import SuccessMessageMixin |
from django.views.generic.edit import CreateView | from django.views.generic.edit import CreateView | ||
from myapp.models import Author | from myapp.models import Author | ||
第504行: | 第437行: | ||
model = Author | model = Author | ||
success_url = '/success/' | success_url = '/success/' | ||
− | success_message = | + | success_message = "%(name)s was created successfully"</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 来自 <code>form</code> 的清理数据可用于使用 <code>%(field_name)s</code> 语法的字符串插值。 对于 ModelForms,如果您需要从保存的 <code>object</code> 访问字段,请覆盖 [[#django.contrib.messages.views.SuccessMessageMixin.get_success_message|get_success_message()]] 方法。 | |
− | |||
− | |||
− | [[#django.contrib.messages.views.SuccessMessageMixin.get_success_message| | ||
− | |||
− | ''' | + | '''ModelForms'''的示例views.py: |
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第521行: | 第450行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">from django.contrib.messages.views import SuccessMessageMixin |
from django.views.generic.edit import CreateView | from django.views.generic.edit import CreateView | ||
from myapp.models import ComplicatedModel | from myapp.models import ComplicatedModel | ||
第528行: | 第457行: | ||
model = ComplicatedModel | model = ComplicatedModel | ||
success_url = '/success/' | success_url = '/success/' | ||
− | success_message = | + | success_message = "%(calculated_field)s was created successfully" |
def get_success_message(self, cleaned_data): | def get_success_message(self, cleaned_data): | ||
第534行: | 第463行: | ||
cleaned_data, | cleaned_data, | ||
calculated_field=self.object.calculated_field, | calculated_field=self.object.calculated_field, | ||
− | )</ | + | )</syntaxhighlight> |
</div> | </div> | ||
第545行: | 第474行: | ||
<div id="expiration-of-messages" class="section"> | <div id="expiration-of-messages" class="section"> | ||
− | == | + | == 消息过期 == |
− | + | 消息被标记为在迭代存储实例时清除(并在处理响应时清除)。 | |
− | |||
− | + | 为避免消息被清除,您可以在迭代后将消息存储设置为<code>False</code>: | |
− | <code>False</code> | ||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第557行: | 第484行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">storage = messages.get_messages(request) |
for message in storage: | for message in storage: | ||
do_something_with(message) | do_something_with(message) | ||
− | storage.used = False</ | + | storage.used = False</syntaxhighlight> |
</div> | </div> | ||
第569行: | 第496行: | ||
<div id="behavior-of-parallel-requests" class="section"> | <div id="behavior-of-parallel-requests" class="section"> | ||
− | == | + | == 并行请求的行为 == |
− | + | 由于 cookie(以及会话)的工作方式,'''当同一个客户端发出多个并行设置或获取消息的请求时,任何使用 cookie 或会话的后端的行为都是未定义的'''。 例如,如果客户端发起一个请求,在一个窗口(或选项卡)中创建一条消息,然后另一个在另一个窗口中获取任何统一消息,则在第一个窗口重定向之前,该消息可能会出现在第二个窗口而不是第一个窗口中可能会出现的窗口。 | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | 简而言之,当涉及来自同一个客户端的多个同时请求时,不能保证消息被传送到创建它们的同一个窗口,在某些情况下,甚至根本不能保证。 请注意,这在大多数应用程序中通常不是问题,并且在 HTML5 中将成为非问题,其中每个窗口/选项卡都有自己的浏览上下文。 | |
− | |||
− | |||
− | |||
− | |||
第589行: | 第506行: | ||
<div id="settings" class="section"> | <div id="settings" class="section"> | ||
− | == | + | == 设置 == |
− | + | 一些 [[../../settings#settings-messages|设置]] 可让您控制消息行为: | |
− | |||
− | * [[ | + | * [[#id25|<span id="id26" class="problematic">:设置:`MESSAGE_LEVEL`</span>]] |
− | * [[ | + | * [[#id27|<span id="id28" class="problematic">:设置:`MESSAGE_STORAGE`</span>]] |
− | * [[ | + | * [[#id29|<span id="id30" class="problematic">:设置:`MESSAGE_TAGS`</span>]] |
− | + | 对于使用 cookie 的后端,cookie 的设置取自会话 cookie 设置: | |
− | |||
− | * [[ | + | * [[#id31|<span id="id32" class="problematic">:设置:`SESSION_COOKIE_DOMAIN`</span>]] |
− | * [[ | + | * [[#id33|<span id="id34" class="problematic">:设置:`SESSION_COOKIE_SECURE`</span>]] |
− | * [[ | + | * [[#id35|<span id="id36" class="problematic">:设置:`SESSION_COOKIE_HTTPONLY`</span>]] |
第609行: | 第524行: | ||
</div> | </div> | ||
+ | <div class="clearer"> | ||
− | [[Category:Django 3.0.x | + | |
+ | |||
+ | </div> | ||
+ | |||
+ | [[Category:Django 3.0.x 文档]] |
2021年10月31日 (日) 04:09的最新版本
消息框架
在 Web 应用程序中,在处理表单或某些其他类型的用户输入后,您需要向用户显示一次性通知消息(也称为“闪现消息”),这很常见。
为此,Django 为匿名和经过身份验证的用户提供对基于 cookie 和会话的消息传递的全面支持。 消息框架允许您在一个请求中临时存储消息并检索它们以在后续请求(通常是下一个请求)中显示。 每条消息都标有确定其优先级的特定 level
(例如,info
、warning
或 error
)。
启用消息
django-admin startproject
创建的默认 settings.py
已经包含启用消息功能所需的所有设置:
'django.contrib.messages'
在 :setting:`INSTALLED_APPS` 中。:setting:`MIDDLEWARE` 包含
'django.contrib.sessions.middleware.SessionMiddleware'
和'django.contrib.messages.middleware.MessageMiddleware'
。默认的 存储后端 依赖于 会话 。 这就是为什么
SessionMiddleware
必须启用并出现在 :setting:`MIDDLEWARE` 中的MessageMiddleware
之前。:setting:`TEMPLATES` 设置中定义的
DjangoTemplates
后端的'context_processors'
选项包含'django.contrib.messages.context_processors.messages'
。
如果您不想使用消息,可以从 :setting:`INSTALLED_APPS`、:setting:` 中的 MessageMiddleware
行中删除 'django.contrib.messages'
MIDDLEWARE`,以及来自 :setting:`TEMPLATES` 的 messages
上下文处理器。
配置消息引擎
存储后端
消息框架可以使用不同的后端来存储临时消息。
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 是默认的存储类。 如果它不适合您的需求,您可以通过将 :setting:`MESSAGE_STORAGE` 设置为其完整导入路径来选择其他存储类,例如:
- class storage.base.BaseStorage
要编写自己的存储类,请在 django.contrib.messages.storage.base
中继承 BaseStorage
类并实现 _get
和 _store
方法。
消息级别
消息框架基于类似于 Python 日志记录模块的可配置级别架构。 消息级别允许您按类型对消息进行分组,以便它们可以在视图和模板中进行过滤或以不同方式显示。
可以直接从django.contrib.messages
中导入的内置关卡有:
常数 | 目的 |
---|---|
DEBUG
|
在生产部署中将被忽略(或删除)的与开发相关的消息 |
INFO
|
给用户的信息性消息 |
SUCCESS
|
一个动作成功,例如 “您的个人资料已成功更新” |
WARNING
|
故障没有发生,但可能即将发生 |
ERROR
|
操作 不 成功或发生其他一些失败 |
:setting:`MESSAGE_LEVEL` 设置可用于更改最小记录级别(或者可以根据请求 更改 )。 尝试添加低于此级别的消息将被忽略。
在视图和模板中使用消息
- add_message(request, level, message, extra_tags=, fail_silently=False)
添加留言
要添加消息,请致电:
一些快捷方法提供了一种标准方式来添加带有常用标签的消息(通常表示为消息的 HTML 类):
显示消息
- get_messages(request)
在你的模板中,使用类似的东西:
如果您使用上下文处理器,则您的模板应使用 RequestContext
呈现。 否则,请确保 messages
可用于模板上下文。
即使您知道只有一条消息,您仍然应该遍历 messages
序列,否则消息存储将不会为下一个请求清除。
上下文处理器还提供了一个 DEFAULT_MESSAGE_LEVELS
变量,它是消息级别名称到其数值的映射:
在模板之外,你可以使用get_messages():
例如,您可以获取所有消息以在 JSONResponseMixin 而不是 TemplateResponseMixin 中返回它们。
get_messages() 将返回配置的存储后端的实例。
Message 类
- class storage.base.Message
- 当您遍历模板中的消息列表时,您得到的是
Message
类的实例。 它们只有几个属性:
message
:消息的实际文本。level
:描述消息类型的整数(请参阅上面的 消息级别 部分)。tags
:由空格分隔的所有消息标签(extra_tags
和level_tag
)组合而成的字符串。extra_tags
:包含此消息的自定义标签的字符串,以空格分隔。 默认为空。level_tag
:级别的字符串表示。 默认情况下,它是关联常量名称的小写版本,但如果需要,可以使用 :setting:`MESSAGE_TAGS` 设置进行更改。
创建自定义消息级别
消息级别只不过是整数,因此您可以定义自己的级别常量并使用它们来创建更多定制的用户反馈,例如:
创建自定义消息级别时,您应该小心避免使现有级别过载。 内置级别的值是:
电平常数 | 价值 |
---|---|
DEBUG
|
10 |
INFO
|
20 |
SUCCESS
|
25 |
WARNING
|
30 |
ERROR
|
40 |
如果您需要在 HTML 或 CSS 中识别自定义级别,则需要通过 :setting:`MESSAGE_TAGS` 设置提供映射。
更改每个请求的最低记录级别
可以通过 set_level
方法为每个请求设置最低记录级别:
类似地,可以通过 get_level
检索当前有效级别:
有关最低记录级别如何运作的更多信息,请参阅上面的 消息级别 。
禁用消息框架时静默失败
如果您正在编写一个可重用的应用程序(或其他代码段)并希望包含消息传递功能,但又不想要求您的用户启用它(如果他们不想启用它),您可以传递一个额外的关键字参数 [ X220X] 到 add_message
方法系列中的任何一个。 例如:
笔记
设置 fail_silently=True
只会隐藏 MessageFailure
,否则会在消息框架禁用并尝试使用 add_message
系列方法之一时发生。 它不会隐藏由于其他原因可能发生的故障。
在基于类的视图中添加消息
- class views.SuccessMessageMixin
- 向基于 FormView 的类添加成功消息属性
- get_success_message(cleaned_data)
cleaned_data
是用于字符串格式化的表单中的清理数据
示例views.py:
来自 form
的清理数据可用于使用 %(field_name)s
语法的字符串插值。 对于 ModelForms,如果您需要从保存的 object
访问字段,请覆盖 get_success_message() 方法。
ModelForms的示例views.py:
消息过期
消息被标记为在迭代存储实例时清除(并在处理响应时清除)。
为避免消息被清除,您可以在迭代后将消息存储设置为False
:
并行请求的行为
由于 cookie(以及会话)的工作方式,当同一个客户端发出多个并行设置或获取消息的请求时,任何使用 cookie 或会话的后端的行为都是未定义的。 例如,如果客户端发起一个请求,在一个窗口(或选项卡)中创建一条消息,然后另一个在另一个窗口中获取任何统一消息,则在第一个窗口重定向之前,该消息可能会出现在第二个窗口而不是第一个窗口中可能会出现的窗口。
简而言之,当涉及来自同一个客户端的多个同时请求时,不能保证消息被传送到创建它们的同一个窗口,在某些情况下,甚至根本不能保证。 请注意,这在大多数应用程序中通常不是问题,并且在 HTML5 中将成为非问题,其中每个窗口/选项卡都有自己的浏览上下文。