[PYTHON] Suppression de double envoi avec Django

Qu'est-ce que la double soumission / la double transmission?

La double soumission signifie que la même demande sera envoyée plusieurs fois. Si le traitement effectué lors de la réception d'une demande POST est exécuté plusieurs fois, un traitement inattendu peut être effectué. Cela peut également être causé par le bouton de rechargement du navigateur, il est donc souhaitable de prendre certaines mesures.

référence

Contre-mesures contre la double soumission de Saikyo

Django a-t-il une fonction de contre-mesure à double soumission?

J'ai cherché patiemment, mais cela ne semblait pas être le cas, alors je l'ai fait moi-même facilement. Il s'agit d'un double jugement de soumission côté serveur et non côté client, comme la désactivation des boutons.

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

Comment utiliser

Dans l'échantillon, le flux est le suivant.

  1. (Serveur-> Client) index Maintenez submit_token dans la session lors de l'accès à l'écran et transmettez-le au client en même temps.
  2. (Client-> Serveur) Incluez submit_token dans la demande lorsque le bouton d'envoi est pressé sur l'écran d'index.
  3. (Serveur) Vérifiez si submit_token est dans la session

Dans exist_submit_token (), submit_token utilisé une fois est écarté de la session par pop, donc si la même requête est envoyée plusieurs fois, error.html sera retourné.

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>

finalement

Je voudrais utiliser une méthode plus simple et plus facile à comprendre, mais j'ai une fois compromis avec l'implémentation ci-dessus. De plus, comme SessionToken dans Struts2, je voudrais pouvoir dire que le même écran sera retourné même après la deuxième fois et les suivantes de la même demande, bien qu'il ne soit pas traité. Si vous avez une bonne bibliothèque, ou si vous voulez faire quelque chose comme ça, faites-le nous savoir dans les commentaires.

Recommended Posts

Suppression de double envoi avec Django
Internationalisation avec Django
CRUD avec Django
Authentifier Google avec Django
Django 1.11 a démarré avec Python3.6
Télécharger des fichiers avec Django
Résumé du développement avec Django
Utiliser Gentelella avec Django
Twitter OAuth avec Django
Premiers pas avec Django 1
Envoyer des e-mails avec Django
Téléchargement de fichiers avec django
Utilisez LESS avec Django
La mutualisation mécanise avec Django
Utiliser MySQL avec Django
Django à partir d'aujourd'hui
Premiers pas avec Django 2
Faites Django avec CodeStar (Python3.6.8, Django2.2.9)
Lancez-vous avec Django! ~ Tutoriel ⑤ ~
Environnement de site Web de configuration minimale avec django
Créer une API avec Django
Faites Django avec CodeStar (Python3.8, Django2.1.15)
Déployer Django sans serveur avec Lambda
Python3 + Django ~ Mac ~ avec Apache
Premiers pas avec Python Django (1)
Créer une page d'accueil avec django
Lancez-vous avec Django! ~ Tutoriel ④ ~
Créer une application Web avec Django
Premiers pas avec Python Django (3)
Combinez Fast API avec Django ORM
Lancez-vous avec Django! ~ Tutoriel ⑥ ~
Utilisez Django pour enregistrer les données de tweet
Effectuer le cryptage AES avec DJango
Introduction à Python Django (6)
Combinez deux images avec Django
Premiers pas avec Django avec PyCharm
Web en temps réel avec les chaînes Django
Framework Django REST avec Vue.js
Utilisez prefetch_related commodément avec Django
Premiers pas avec Python Django (5)
Connectez-vous avec Django Rest Framework
Qiita API Oauth avec Django
Développement piloté par les tests avec Django Partie 3
recharger dans le shell django avec ipython
Étapes pour développer Django avec VSCode
Développement piloté par les tests avec Django Partie 4
Empêcher le double lancement de la commande django
Charger les modules Django avec un interpréteur
Configurer la connexion sociale avec Django
Développement piloté par les tests avec Django Partie 6
Mesurer la couverture des applications Django avec Coverage.py
Gérer les fichiers csv avec Django (django-import-export)
HTTPS avec Django et Let's Encrypt
Gérer les fichiers de configuration Django avec Python-decouple
Déployer l'application Django avec Docker
Standardiser le HTML à louer avec Django
Jointure externe gauche dans le modèle Django
Développement piloté par les tests avec Django Partie 2
Django Tips-Créez un site de classement avec Django-
Application de publication sur Twitter réalisée avec Django
Générer automatiquement un diagramme de relation de modèle avec Django