0

I have some "save" code that sets a success message using the Django messaging framework upon successful creation of a record, then does a redirect back to the main 'application_update' view. I'm having trouble determining why these messages are not making it thru the redirect. The messaging seems to work just fine when doing a "render_to_response", but not when doing a "redirect".

function snippet (if POST) in views.py:

if ovrd_form.is_valid():
    fields = {'application': ovrd_form.cleaned_data['application'],
              'course': ovrd_form.cleaned_data['course'],
              * other field/values *
             }
    try:
        overrides = Overrides(**fields)
        overrides.save()
        success_msg = 'Override creation was successful.'
        create_message(request, success_msg, 'success')
    except Exception, exception:
        return HttpResponse('Error: ' + str(exception))

    return redirect('application_update', app_id=app_id)

create_message() function:

from django.contrib import messages

def create_message(request, msg, msg_type):
    """ build a message & sets the correct message.type """
    if msg_type == 'error':
        django.contrib.messages.error(request, msg)
    elif msg_type == 'warning':
        django.contrib.messages.warning(request, msg)
    elif msg_type == 'success':
        django.contrib.messages.success(request, msg)
    elif msg_type == 'info':
        django.contrib.messages.info(request, msg)
    elif msg_type == 'debug':
        django.contrib.messages.debug(request, msg)

all templates inherit this piece of code:

{% if messages %}
    {% for message in messages %}
        {% comment %}force -danger if error type for bootstrap css class{% endcomment %}
        {% if message.tags == 'error' %}
            <div class="alert alert-danger">
        {% else %}
            <div class="alert alert-{{ message.tags }}">
        {% endif %}
            <button type="button" class="close" data-dismiss="alert">&times;</button>
            <span>{{ message }}</span>
            </div>
    {% endfor %}
{% endif %}

Any help would be very much appreciated.

ppython
  • 485
  • 6
  • 19
KeithE
  • 216
  • 2
  • 11

4 Answers4

1

We use a function similar to the one below to preserve messages after one or more redirects:

# Preserve any error messages... ie. if a redirect results in another
# redirect.  

from django.contrib import messages

def preserve_error_messages( request ):
    mstore = messages.get_messages( request )
    for m in mstore:
        messages.add_message( request, m.level, m.message, extra_tags = m.extra_tags )
    return

EDIT: This is equivalent to preventing messages from being cleared/expired: https://docs.djangoproject.com/en/1.4/ref/contrib/messages/#expiration-of-messages

Travis D.
  • 342
  • 1
  • 9
  • Now I get it. But you're not setting `storage.used = False` anywhere, right? I'm guessing that doesn't matter? – KeithE Apr 24 '14 at 22:26
  • I'm re-adding the messages instead. (Not sure why I got downvoted...?!) – Travis D. Apr 24 '14 at 22:31
  • Not sure why the downvote either Travis. I did work this in to my project when attempting to get things working, and it did just fine. In the end, however, I got my messages working thru the redirect and therefore did not use your solution long-term. Thanks a ton for posting it though! P.S. I gave you an upvote in the hopes of balancing it back out a bit. – KeithE Apr 28 '14 at 13:27
1

You need to use a RequestContext in your destination view in order to pass the message into the template. The easiest way to do that is to use the render shortcut rather than render_to_response:

return render(request, 'view.html', {'form': ovrd_form})

Note that the first parameter is the request object.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Will that also pick up my context dict? – KeithE Apr 24 '14 at 23:39
  • That `{'form': ovrd_form}` *is* your context dict. I have no idea what that other parameter there you've called context is doing. – Daniel Roseman Apr 25 '14 at 06:44
  • Actually, the "context" parm I was passing in the original render_to_response was a pretty important dict. I figured out how to get it to pass correctly in the render statement as such: `return render(request, 'view.html', {'form': app_form, 'note_form': note_form}, context_instance=context)`. Now I'm back to square one though...the messages are still not going thru. Any thoughts? – KeithE Apr 25 '14 at 13:34
  • UPDATE: I found that we do build a sub-class of DirectContext and it gets passed in the "context" dict. However, this works in the render_to_response method, and can be made to work in the render method as long as I set context_instance=context. Not sure if that is somehow overwriting the request vars that are needed to pass the messages though. ?? – KeithE Apr 25 '14 at 14:57
  • @DanielRoseman: Hi Daniel. Can you help me resolving this: http://stackoverflow.com/questions/32600473/django-messages-not-showing-after-httpresponseredirect Struggling with this for so long. – Parag Tyagi Sep 16 '15 at 05:56
0

Eureka! Sort of. It would seem that I may have either needed to reboot my VM session (can’t see how this would be it, but stranger things…) or I needed to clear my browser cache (session parms).

Reboot of VM: from time to time I experience internal clock issues with my Vagrant VM box which results in Oauth discrepancies, which in turn causes my REST API calls to fail, which is corrected once I reboot the SSH session and/or vagrant halt and vagrant up my VM. How does this tie in to my messaging problem? Not sure it does, only stating that I may be getting some VM corruption over time that could affect more than what I’m aware of. Lesson learned for me is to reboot the VM anytime I have weirdness that just doesn’t add up.

  • Note: I don’t shutdown my VM or computer every night, and I do carry it home. This means it has to make contact with different wifi networks, and that causes me to have to restart my SSH terminal often. The VM is therefore run for days…or at least till it gets buggy.

Clear my cache: I made myself forget about this problem over the weekend and when I started working on it this morning…walla! All is well. I had to do the VM thing stated above before trying to reload the page (to get the auths problem fixed), so I’m not certain if the correction came from that or just because my session parms likely expired.

Thanks to @TravisD & @DanielRoseman for the help!

KeithE
  • 216
  • 2
  • 11
0

Added below in local_settings.py and it is working.

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

Know more here.

Community
  • 1
  • 1
Parag Tyagi
  • 8,780
  • 3
  • 42
  • 47