How to clear POST data in Django – ‘Confirm Form Resubmission’ // 1-minute guide

After submiting data via form you keep getting this annoying ‘Confirm Form Resubmission’ alert from Google Chrome? Here is the solution.

Sidenote: this specific example of clearing POST data uses a simple html form and a class-based view.

So here is the offending message:

Annoying Google Chrome message

No more resubmission

In post() function instead of render:

from django.views.generic import TemplateView
from django.shortcuts import render

class CoolView(TemplateView):
   def post(self, request, *args, **kwargs):
      ''' Anything you need '''
      return render(request, template_name, context)

use HttpResponseRedirect():

from django.views.generic import TemplateView
from django.http import HttpResponseRedirect

class CoolView(TemplateView):
   def post(self, request, *args, **kwargs):
      ''' Anything you need '''
      return HttpResponseRedirect(request.path)

Refresh the page and voila! Everything is perfect. Or is it?..

Success Message

In order to somehow tell the user that the form is successfully (or not) processed, I will send them a message (e.g. a dismissable banner is a good practice).

If you use context[‘messages’], delete it and use django.contrib.messages instead.

from django.views.generic import TemplateView
from django.http import HttpResponseRedirect
from django.contrib import messages

class CoolView(TemplateView):
   def post(self, request, *args, **kwargs):
      ''' Anything you need '''
      messages.success(request, 'Success!')
      return HttpResponseRedirect(request.path)

In order to set a message in post() set the message:

To work with messages on the template use this (where message.tag is ‘success’) iteration of all of the messages in session right now:

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

If you are using this thing with only immediate interactions, you will be fine. E.g. for Celery, I would recommend models.

But now the messages are stacked. And I used this with other forms. Soon the list of messages is higher than the Empire State! Oops… So to resolve this, in get() clear it:

from django.views.generic import TemplateView
from django.contrib import messages

class CoolView(TemplateView):
   def get(self, request, *args, **kwargs):
      system_messages = messages.get_messages(request)
      for message in system_messages:
         pass
         system_messages.used = True     
         return render(request, self.template_name, self.context)

This way the messages array will only have one message. What a beauty!

Context

If, by chance, you need to pass some extra context data to the template, with HttpResponseRedirect you need to use:

request.session['other_data'] = 'wow'

Just add it somewhere, like this:

from django.views.generic import TemplateView
from django.http import HttpResponseRedirect
from django.contrib import messages

class CoolView(TemplateView):
   def post(self, request, *args, **kwargs):
      ''' Anything you need '''
      messages.success(request, 'Success!')
      request.session['other_data'] = 'wow'
      return HttpResponseRedirect(request.path)

If you keep it like that, even after reloading the page, this context data will remain on the page. I am in the process of figuring out how to fix that. (edit 13.10.2019)

Thank you for your attention.

This post was born with the help of awesome people on StackOverFlow (one and two). 

References

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.