[PYTHON] Double submit suppression with Django

What is double submit / double transmission?

Double submit means that the same request will be sent multiple times. If the processing performed when a POST request is received is executed multiple times, unexpected processing may be performed. It can also be caused by the reload button of the browser, so it is desirable to take some measures.

reference

Countermeasures for double submission of Saikyo

Does Django have a double submit feature?

I searched patiently, but it didn't seem to be so, so I made it myself easily. It is a double submit judgment on the server side, not on the client side such as button deactivation.

def set_submit_token(request):
    submit_token = str(uuid.uuid4())
    request.session['submit_token'] = submit_token
    return submit_token

def exists_submit_token(request):
    token_in_request = request.POST.get('submit_token')
    token_in_session = request.session.POP('submit_token', '')

    if not token_in_request:
        return False
    if not token_in_session:
        return False

    return token_in_request == token_in_session

How to use

In the sample, the flow is as follows.

  1. (Server-> Client) index Hold submit_token in session when screen is accessed, and pass it to client at the same time.
  2. (Client-> Server) Include submit_token in the request when the submit button is pressed on the index screen.
  3. (Server) Check if submit_token is in the session

In exists_submit_token (), submit_token used once is discarded from the session by pop, so if the same request is sent multiple times, error.html will be returned.

views.py


def index(request):
    submit_token = set_submit_token(request)
    return render(request, 'todo/index.html', {"submit_token": submit_token})

def post(request):
    if not exists_submit_token(request):
        return render(request, 'todo/error.html', {})
    else:
        return render(request, 'todo/complete.html', {})

index.html


<form action="{% url 'todo:post' %}" method="post">
{% csrf_token %}
{{ submit_token }}
<input type="hidden" name="submit_token" value="{{ submit_token }}" />
<input type="submit" value="Submit" />
</form>

Finally

I would like to use a simpler and easier-to-understand method, but I once compromised with the above implementation. Also, like SessionToken in Struts2, I would like to be able to say that the exact same screen will be returned even after the second and subsequent times of the same request, although it will not be processed. If you have a good library or something you should do, please let us know in the comments.

Recommended Posts

Double submit suppression with Django
Internationalization with django
CRUD with Django
Authenticate Google with Django
Django 1.11 started with Python3.6
Upload files with Django
Development digest with Django
Use Gentelella with django
Twitter OAuth with Django
Getting Started with Django 1
Send email with Django
File upload with django
Use LESS with Django
Pooling mechanize with Django
Use MySQL with Django
Start today with Django
Getting Started with Django 2
Do Django with CodeStar (Python3.6.8, Django2.2.9)
Get started with Django! ~ Tutorial ⑤ ~
Minimal website environment with django
Create an API with Django
Do Django with CodeStar (Python3.8, Django2.1.15)
Deploy Django serverless with Lambda
Python3 + Django ~ Mac ~ with Apache
Getting Started with Python Django (1)
Create a homepage with django
Get started with Django! ~ Tutorial ④ ~
Web application creation with Django
Getting Started with Python Django (3)
Combine FastAPI with Django ORM
Get started with Django! ~ Tutorial ⑥ ~
Save tweet data with Django
Do AES encryption with DJango
Getting Started with Python Django (6)
Combine two images with Django
Getting Started with Django with PyCharm
Real-time web with Django Channels
Django REST framework with Vue.js
Use prefetch_related conveniently with Django
Getting Started with Python Django (5)
Login with django rest framework
Qiita API Oauth with Django
Test Driven Development with Django Part 3
reload in django shell with ipython
Steps to develop Django with VSCode
Test Driven Development with Django Part 4
Prevent double launch of django commands
Load Django modules with an interpreter
Set up social login with Django
Test Driven Development with Django Part 6
Measure Django application coverage with Coverage.py
Handle csv files with Django (django-import-export)
HTTPS with Django and Let's Encrypt
Manage Django config files with Python-decouple
Deploy a Django application with Docker
Common html to rent with Django
Django Model with left outer join
Test Driven Development with Django Part 2
Django Tips-Create a ranking site with Django-
Twitter posting application made with Django
Automatically generate model relationships with Django