21đ
Client side, start with JavaScript. You can never trust the client, but its a start.
i.e.
onclick="this.disabled=true,this.form.submit();
Server side you âcouldâ insert something into a database i.e. a checksum. If its a records you are insert into a database use model.objects.get_or_create()
to force the uniqueness on database level you should use unique_together.
Lastly: HTTPRedirect is best, The the method I use when a user processes a payment is to just issue a HTTPRedirect() to the thank you/conformation page. This way refreshing the form wonât resubmit and if they go back and try to submit the form again (without refreshing the form) the Django Cross Site Request Forgery (CSRF) will fail, perfect!
4đ
I also try to find a good way to prevent double records generation when a user dbl-click on a submit button.
Itâs not about the PRG issue that is easily fixed by redirection.
So, regards on this basic concern, the solution with HTTPRedirect on server-side doesnât help.
On client-side, I found two problems when I disable the button before submit:
- With HTML5 validation, the
form.submit()
will be interupted by browser if the form is invalid => submit button is stilldisabled=true
. - When the user submit the form and do a back in browser history, the DOM will be loaded from browserâs cache => submit button is still
disabled=true
.
So here is my workaround for the first client-side problem (HTML5 validation):
isFormHtml5Valid(form) {
for(var el of form.querySelectorAll('input,textarea,select')){
if(!el.checkValidity())
return false;
}
return true;
}
mySubmitButton.onclick = function() {
if(this.form && isFormHtml5Valid(this.form))
this.disabled=true;
this.form.submit();
}
I try to find a client-side workaround for the second client-side problem (browser cache the DOM) but nothing worked (onbeforeunload, âŠ).
So the workaround I currently use for âbrowser cacheâ issue is add a @never_cache decoration on the top of concerned views (from server-side, indicate to client-side to not caching). Please let me know if you have a better workaround.
Last but not least, I would really appreciate to fix this issue on server side.
The CSRF solution seems not suitable since a CSRF token is generated by session (not for each form).
So here is the status of my work and my question:
- Fix this issue on client-side is OK but doesnât look like a good solution to me. How could we avoid to validate this multiple form submition on server-side?
Let me know if you have a good solution for that.
Edit 1:
May be a small part of the answer: Synchronizer (or DĂ©jĂ vu) Token
But I didnât find any implemantation of that in Django.
- Django / postgres setup for database creation, for running tests
- Connect refused in response to Django runserver
- Unknown command: shell_plus and âsettings
- How to prevent self (recursive) selection for FK / MTM fields in the Django Admin
- Unsupported media type Django API
1đ
Use HttpResponseRedirect
create a new view(lets say thank_you
) for successful message to display after form submission and return a template.
After successful form submission do return HttpResponseRedirect(â/thank-you/â) to the new thank-you view
from django.http import HttpResponseRedirect
def thank_you(request, template_name='thank-you.html'):
return render_to_response(template_name,locals(),context_instance=RequestContext(request))
and in urls.py
url(r'^thank-you/$','thank_you', name="thank_you")
Multiple form submission happens because when page refreshes that same url hits, which call that same view again and again and hence multiple entries saved in database. To prevent this, we are required to redirect the response to the new url/view, so that next time page refreshes it will hit that new url/view.
0đ
- After a successful submission respond with a redirect so a reload doesnât cause another submission
- Disable the submit button on form submission
As for #2, itâs best to do that in the onsubmit
handler and not the onclick
for the submit button. This will handle cases such as multiple submit buttons or if thereâs any HTML5 client-side form validation. In jQuery itâd look something like:
$('#edit_form').submit( function(event) {
// disable to avoid double submission
$('#submit_button').attr('disabled', true);
});
However, one issue this doesnât account for is if the user cancels the submit part way. For example, if you click âsubmitâ and then immediately hit âEscâ, the browser will stop the submission but âsubmitâ button will already be disabled.
Also, itâs possible to have a form that is submitted by hitting âenterâ and this solution wouldnât prevent that form from submitting twice.
- Django filter with OR condition using dict argument
- How to read sql query to pandas dataframe / python / django
- How to customise django inline admin form's delete function
- What is the use of __table_args__ = {'extend_existing': True} in SQLAlchemy?