防止在Django多个表单提交(Prevent multiple form submissions

2019-08-18 02:17发布

我在寻找一种通用的方法,以防止多个表单提交。 我发现这个方法看起来很有希望。 虽然我不想包含这个片段在我所有的意见。 它可能更容易与请求处理器或中间件来做到这一点。

任何最佳实践的建议?

Answer 1:

客户端,开始使用JavaScript。 你永远不能信任的客户端,但它的一个开端。

onclick="this.disabled=true,this.form.submit();

服务器端你“可以”插入一些内容即校验数据库。 如果它是一个记录你插入到数据库中使用model.objects.get_or_create()来强制你应该使用unique_together数据库级别的唯一性。

最后 :HTTPRedirect是最好的,我在用,当用户处理付款是刚刚发出HTTPRedirect()将感谢你/构造页面的方法。 这样,刷新表单不会再次提交,如果他们回去,并尝试重新提交表单(而不刷新形式)Django的跨站请求伪造(CSRF)会失败,完美!



Answer 2:

我也试图寻找避免重复记录产生一个很好的方式,当用户在一个提交按钮DBL点击。 这不是关于PRG问题是容易被重定向固定。

所以,在此基础关心的问候,在服务器端与HTTPRedirect解决没有帮助。

在客户端,我发现了两个问题,当我禁用按钮之前提交:

  1. 与HTML5验证, form.submit()将被浏览器,如果表单是无效=>提交按钮仍所中断disabled=true
  2. 当用户提交表单,并做浏览器历史上的一个回来,DOM会从浏览器缓存加载=>提交按钮仍然disabled=true

因此,这里是我的第一个客户端的问题(HTML5验证)的解决方法:

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();
}

我试图找到一个客户端的解决方法为第二客户端的问题(浏览器缓存中的DOM),但毫无效果(onbeforeunload,...)。 所以,我目前使用的“浏览器缓存”问题的解决方法是增加对有关意见顶部的@never_cache装修(从服务器端,指示客户端不缓存)。 请让我知道,如果你有更好的解决方法。

最后但并非最不重要的, 我会很感激固定在服务器端这个问题 。 由于该CSRF溶液似乎不适合由会话生成CSRF令牌 (未每种形式)。 因此,这里是我的工作和我的问题的状态:

  • 修正了在客户端解决此问题是确定的,但看起来并不像一个很好的解决方案给我。 我们怎么能避免验证服务器端这种多形式submition?

让我知道,如果你有专门的好办法。


编辑1:可能是答案的一小部分: 同步(或似曾相识)令牌

但我没有找到在Django的任何implemantation。



Answer 3:

使用HttpResponseRedirect

创建一个新的视图(可以说thank_you )成功的消息表单提交后显示,并返回一个模板。

成功的表单提交后返回HttpResponseRedirect(“/感谢你/”)到新感谢您查看

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))

在urls.py

url(r'^thank-you/$','thank_you', name="thank_you")

多形式提交是因为当页面刷新相同的URL访问,这调用同样的观点连连,因此多个条目保存在数据库中。 为了防止这种情况,我们需要重定向到新的URL /视图中的反应,所以下一次页面刷新,这将创下新的URL /视图。



Answer 4:

  1. 在成功提交一个重定向响应所以重装不会导致另一个提交
  2. 禁止提交表单提交按钮

至于#2,这是最好做的是,在onsubmit处理程序,而不是onclick提交按钮。 如多个提交按钮这将处理案件或是否有任何HTML5客户端表单验证。 在jQuery中它会看起来像:

$('#edit_form').submit( function(event) {
    // disable to avoid double submission
    $('#submit_button').attr('disabled', true);
});

然而,有一个问题,这并不考虑是,如果用户取消部分提交方式。 例如,如果你点击“提交”,然后立即按下“Esc”键,浏览器将停止提交,但“提交”按钮,将已被禁用。

此外,它可能有一个由打“进入”提交,该解决方案将无法阻止这种形式从两次提交表单。



文章来源: Prevent multiple form submissions in Django