amy icon indicating copy to clipboard operation
amy copied to clipboard

Double clicking submit button creates duplicate records

Open elichad opened this issue 1 year ago • 3 comments

In views that create a new record (i.e. not those that update an existing one), double clicking on the submit button can reliably create a duplicate record - i.e. the POST request is created and handled twice.

I keep running into this because of my particular (unusual) mousing patterns and impatience with slightly slow page loads. I've replicated this locally and in test-amy, but haven't tried production. It's slightly annoying, but generally harmless.

I assume that there are some common strategies to avoid this for websites in general, and that we can look into applying one of those here.

Screenshot of fake trainee with duplicate Welcome Session and Training records

elichad avatar Aug 09 '23 13:08 elichad

From @elichad - Unsure about what it would take to fix it. Has seen it handled on other sites; need to research how this happens. Possibly disable button after clicking once to prevent it from being clicked again.

maneesha avatar Aug 15 '23 14:08 maneesha

The key concept here is known as idempotence/idempotency.

I'm roughly following this article to implement this for our Create* views: Idempotence and POST Requests in Django. This should be a bit more robust than disabling buttons on submit.

Progress on branch feature/2511-Double-clicking-submit-button-creates-duplicate-records

Extra info on an implementation in a major API: https://stripe.com/docs/api/idempotent_requests

Current status:

  • [x] implement a mixin to make create views idempotent
  • [x] implement middleware to catch duplicate requests
  • [ ] figure out what response to return that results in the user seeing the same as they usually would
  • [x] create template tag to add idempotence tokens to POST forms, like CSRF tokens
  • [ ] ensure all views work as before
  • [ ] write plenty of tests

elichad avatar Nov 01 '23 17:11 elichad

There is a lazier option here, which is to insert a bit of JS everywhere to disable submit buttons on submit. But the solution described above would work for both web and API requests, whereas JS works for web only. Disabling buttons is also not great for accessibility (though in this context, it's not too bad).

elichad avatar Dec 01 '23 16:12 elichad