HttpResponseRedirect 后不显示 Django 消息

Django messages not showing after HttpResponseRedirect

尝试了很多东西,但 none 确实有用。

我有一个 URL 例如:

http://localhost:8000/user/edit-transaction/?object_id=23a959d0561711e59e36acd1b8679265&type=grossary

调用下面的 view:

def edit_transaction(request):

    if request.method == "POST":
        if something is True:
            messages.error(request, 'Error message here')

            # this don't work
            return HttpResponseRedirect(request.META.get('HTTP_REFERER'))

            # but this work
            template = "user/xyz/abc.html"
            render(request, template)
        else:
            return HttpResponseNotFound()
    else:
        context = {
             'key1': 'value1', 
             'key2': 'value2',
        }
        template = "user/xyz/abc.html"
        render(request, template, context)

以及内部模板:

{% if messages %}

<h1>I am inside MESSAGES</h1>

    {% for message in messages %}
        {% if message.tags == 'success' %}
            <div class="alert alert-success" role="alert">{{ message|escape|safe }}</div>
        {% elif message.tags == 'error' %}
            <div class="alert alert-danger" role="alert">{{ message|escape|safe }}</div>
        {% endif %}
    {% endfor %}
{% endif %}

它进入 if 此处 if something is True: 并被重定向到与查询字符串相同的页面。但不显示错误信息。

我想要的是重定向到保留查询字符串的同一页面并显示错误消息。我在这里做错了什么以及建议进行哪些更改(如果有的话)。

Also a doubt, that does Django messages really work after redirection like Flash messages should ??


编辑:

1) 这行不通:

if something is True:
    messages.error(request, 'Error message here')
    return HttpResponseRedirect(request.META.get('HTTP_REFERER'))

来自控制台:

[16/Sep/2015 10:57:08]"POST /user/edit-transaction/?object_id=23a959d0561711e59e36acd1b8679265&type=grossary HTTP/1.1" 302 0 [16/Sep/2015 10:57:08]"GET /user/edit-transaction/?object_id=23a959d0561711e59e36acd1b8679265&type=grossary HTTP/1.1" 200 8832

2) 这有效:

if something is True:
    messages.error(request, 'Error message here')
    template = "user/xyz/abc.html"
    render(request, template)

来自控制台:

[16/Sep/2015 10:57:08]"POST /user/edit-transaction/?object_id=23a959d0561711e59e36acd1b8679265&type=grossary HTTP/1.1" 302 0

所以,基本上我从上面了解到的是 messages 因额外请求(重定向,200)而过期。

并且在模板中,它不会进入 {% if messages %} 以及打印 <h1>I am inside MESSAGES</h1>

终于想通了。在下面添加 local_settings.py 及其 working.

MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'


发生了什么事?

消息实际上存储在 Cookies (CookieStorage) 中,这是默认的 Django 行为。来自 Django docs:

FallbackStorage is the default storage class. If it isn’t suitable to your needs, you can select another storage class by setting MESSAGE_STORAGE to its full import path, for example:

MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'

什么是 FallbackStorage?

This class first uses CookieStorage, and falls back to using SessionStorage for the messages that could not fit in a single cookie. It also requires Django’s contrib.sessions application.

This behavior avoids writing to the session whenever possible. It should provide the best performance in the general case.

我的情况是怎样的?

Messages 被存储在 CookiesStorage 中,但由于某些奇怪的原因(我不知道是什么原因)但是 CookiesStorage 中的 Messages 已过期或为第二次请求删除(即 POST 之后的重定向),这不应该发生(因为这不是 flashdata 的工作方式)。在我将默认 MESSAGE_STORAGE 切换为 SessionStorage 后,它开始工作了。

在我的例子中,修改@ParagTyagi 提到的 MESSAGE_STORAGE 值是不够的。我有一些管理员 类 的自定义 change_list.html 模板,在这些模板中我必须添加以下代码:

{% if messages %}
    <ul class="messages">
        {% for message in messages %}
            <!--li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li-->
        {% endfor %}
   </ul>
{% endif %}

请注意,我已经注释了 <li> 标签,否则消息会重复。

此外,messages对象中的消息必须不止一条。否则,消息也不会显示。如果您只有一条消息要显示(例如,确认操作成功),则只需添加另一条空消息,如:

messages.add_message(self.request, messages.WARNING, "")

修改完成后,记得重启您的网络服务器(例如Apache)并清除您的浏览器缓存。