Django messages not showing after HttpResponseRedirect

Parag Tyagi picture Parag Tyagi · Sep 16, 2015 · Viewed 9.2k times · Source

Tried tonnes of stuff out there but none of them really helped.

I have a URL for example:

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

which calls the below 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)

And inside template:

{% 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 %}

It's getting inside the if here if something is True: and getting redirected to the same page with the query string as well. But not displaying the error message.

What I want is to redirect to the same page preserving the query string and display the error message. What am I doing wrong here and what changes are recommended (if any).

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


Edit:

1) This don't work:

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

From console:

[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) This works:

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

From console:

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

So, basically what I understood from above is that the messages is getting expired with an additional request (redirect, 200).

And in templates, it is not getting inside the {% if messages %} as well to print <h1>I am inside MESSAGES</h1>

Answer

Parag Tyagi picture Parag Tyagi · Sep 18, 2015

Finally figured it out. Added below in local_settings.py and its working.

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


What was happening ?

The messages were actually getting stored in Cookies (CookieStorage) which is the default Django behaviour. From 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'

And what is 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.

And what was happening in my case ?

Messages were getting stored in CookiesStorage, but for some weird reason (I don't know what) but the Messages in CookiesStorage were getting expired or deleted for the 2nd request (i.e. redirection after POST) which should not be happening (because this is not how flashdata works). And after I switched the default MESSAGE_STORAGE to SessionStorage, it started working.