How do I redirect in Django with context?

DjangoDjango Urls

Django Problem Overview


I have a view that validates and saves a form. After the form is saved, I'd like redirect back to a list_object view with a success message "form for customer xyz was successfully updated..."

HttpResponseRedirect doesn't seem like it would work, because it only has an argument for the url, no way to pass dictionary with it.

I've tried modifying my wrapper for object_list to take a dict as a parameter that has the necessary context. I the return a call to this wrapper from inside the view that saves the form. However, when the page is rendered, the url is '/customer_form/' rather than '/list_customers/'. I tried modifying the request object, before passing it to the object_list wrapper, but that did not work.

Thanks.

Django Solutions


Solution 1 - Django

request.user.message_set was deprecated in Django 1.2 and has been removed since Django 1.4, the message framework should be used instead.

from django.contrib import messages

# messages.add_message(request, level, message, extra_tags='', fail_silently=False)
messages.add_message(request, messages.INFO, "Your Message")

Alternatively, you can use one of the shortcut functions:

from django.contrib import messages

messages.debug(request, "Your Message")
messages.info(request, "Your Message")
messages.success(request, "Your Message")
messages.warning(request, "Your Message")
messages.error(request, "Your Message")

Messages can then be rendered on the template with:

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

Solution 2 - Django

Please note the answer suggested here is only applicable to Django < 1.2:

Do you have control over the view that you are redirecting to? In that case you can save the context in the session before redirecting. The target view can pick up the context (and delete it) from the session and use it to render the template.

If your only requirement is to display a message then there is a better way to do this. Your first view can create a message for the current using auth and have the second view read and delete it. Something like this:

def save_form(request, *args, **kwargs):
    # all goes well
    message = _("form for customer xyz was successfully updated...")
    request.user.message_set.create(message = message)
    return redirect('list_view')

def list_view(request, *args, **kwargs):
    # Render page

# Template for list_view:
{% for message in messages %}
   ... 
{% endfor %}

Messages are saved to the database. This means that you can access them even after a redirect. They are automatically read and deleted on rendering the template. You will have to use RequestContext for this to work.

For Django => 1.2 read the answer involving messages

Solution 3 - Django

To expand on Antoine's helpful answer: if you want to process the messages in your views module, rather than the template:

from django.contrib.messages import get_messages

def my_view(request):
    # Process your form data from the POST, or whatever you need to do

    # Add the messages, as mentioned above
    messages.add_message(request, messages.INFO, form.cleaned_data['name'])

    return HttpResponseRedirect('/other_view_url/')

def other_view(request):
    storage = get_messages(request)
    name = None
    for message in storage:
	    name = message
	    break
    return render(request, 'general/other_view.html', {'name': name})

Solution 4 - Django

I found the following to work if more than just a message needs to be added to the redirect:

from django.shortcuts import redirect
import urllib

def my_view(request):
            
    ...
    
    context = {'foo1': bar1, 'foo2': bar2, 'foo3': bar3}
    return redirect('/redirect_link/?' + urllib.parse.urlencode(context))

See also https://stackoverflow.com/questions/34564053/how-to-pass-context-data-with-django-redirect-function/34565763#34565763

Solution 5 - Django

In Django 2.x + you can simply use messages framework that comes with Django

views.py

from django.contrib import messages

def register(request):
    ....
    messages.success(request,"You have registered successfully, now login!")
    return redirect('login-page')

And in you, login.html template do add this code

  {% if messages %}
    {% for message in messages %}
        <div class="alert alert-success alert-dismissible fade show">
            <strong>Success!</strong> {{message}}
            <button type="button" class="close" data-dismiss="alert">&times;</button>
        </div>
    {% endfor %}
 {% endif %}

Note this example can be applied to anywhere you want to display a message for success

If you want to pass an error message simply use messages.error(request, "Error message")

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKevinView Question on Stackoverflow
Solution 1 - DjangoAntoine PinsardView Answer on Stackoverflow
Solution 2 - DjangoManoj GovindanView Answer on Stackoverflow
Solution 3 - DjangoFedererView Answer on Stackoverflow
Solution 4 - DjangoEngensmaxView Answer on Stackoverflow
Solution 5 - DjangoMathews MusukumaView Answer on Stackoverflow