34

I have a page with a POST form, that have a action set to some url.
i.e assume this page url is /form_url/ : ..

The view in /submit_url/ take care of the form data. After this, I want to return the same page of the form with a success message. In the view that take care for the POST form, I use HttpResponseRedirect, in order to "clear" the form data from the browser. But in this way I can't display a message in the form page, unless I do something like:

return HttpResponseRedirect("/form_url/?success=1")

and then check for this parameter in the template. I don't like this way, since if the user refreshes the page, he will still see the success message.

I've noticed that in django admin site, the delete/add of objects does use redirect after POST submit, and still display a success message somehow. How?

I've already briefly seen django "messaging" app, but I want to know how it work first..

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
user3599803
  • 6,435
  • 17
  • 69
  • 130

6 Answers6

70

The django admin uses django.contrib.messages, you use it like this:

In your view:

from django.contrib import messages

def my_view(request):
    ...
       if form.is_valid():
          ....
          messages.success(request, 'Form submission successful')

And in your templates:

{% if messages %}
<ul class="messages">
    {% for message in messages %}
    <li  {% if message.tags %} class=" {{ message.tags }} " {% endif %}> {{ message }} </li>
    {% endfor %}
</ul>
{% endif %}
Krishna Jangid
  • 4,961
  • 5
  • 27
  • 33
damio
  • 6,041
  • 3
  • 39
  • 58
12

For Class Based Views use self.request

I also use self.request.path_info in my return

from django.contrib import messages

class MyCreateView(CreateView):
    ...
       def form_valid(self, form):
          ....
          self.object.save()

          messages.success(self.request, 'Form submission successful')
          
          return HttpResponseRedirect(self.request.path_info)

Same template as damio's answer:

{% if messages %}
<ul class="messages">
    {% for message in messages %}
    <li  {% if message.tags %} class=" {{ message.tags }} " {% endif %}> {{ message }} </li>
    {% endfor %}
</ul>
{% endif %}
Brendan Metcalfe
  • 753
  • 10
  • 10
7
from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.edit import CreateView 
from myapp.models import Author

class AuthorCreate(SuccessMessageMixin, CreateView):
    model = Author
    success_url = '/success/'
    success_message = "%(name)s was created successfully"

https://docs.djangoproject.com/en/1.11/ref/contrib/messages/

Neeraj Kumar
  • 771
  • 2
  • 16
  • 37
Asif
  • 479
  • 2
  • 6
  • 12
6

You don't need to do a redirect to clear the form data. All you need to do is re-instantiate the form:

def your_view(request):
    form = YourForm(request.POST or None)
    success = False
    if request.method == 'POST':
        if form.is_valid():
            form.save()
            form = YourForm()
            success = True
    return render(request, 'your_template.html', {'form': form})

If the user refreshes the page, they're going to initiate a GET request, and success will be False. Either way, the form will be unbound on a GET, or on a successful POST.

If you leverage the messages framework, you'll still need to add a conditional in the template to display the messages if they exist or not.

Brandon Taylor
  • 33,823
  • 15
  • 104
  • 144
  • 4
    If I use render() to return a response from a view which is requsted by POST, then if the user refreshes the page the browser will prompt a popup if to send the form again. That's what I'm trying to avoid. – user3599803 Feb 25 '15 at 18:51
  • You really don't have much of a choice here. You either need to issue a redirect and pass the querystring parameter, or you need to use a message/session value. – Brandon Taylor Feb 25 '15 at 20:16
  • Does the django message app clear the session data after it is used ? Since there is no need to save the session after I display it. – user3599803 Feb 26 '15 at 11:12
  • Yes. Each message is only shown once per request cycle. – Brandon Taylor Feb 26 '15 at 11:50
5

Django messages framework stores the messages in the session or cookie (it depends on the storage backend).

catavaran
  • 44,703
  • 8
  • 98
  • 85
0

If you're using a classed based view with django forms, and granted you've got the messages.html template set up, you can simply pass the 'SuccessMessageMixin' into your view like below

class YourView(SuccessMessageMixin,View):
        success_message = 'your message_here'

This will display your message upon form success