【问题标题】:Django: what is the best way to prevent multiple click on a button?Django:防止多次单击按钮的最佳方法是什么?
【发布时间】:2020-09-25 16:44:58
【问题描述】:

在表单验证之前,我有一个带有弹出确认的 Django 表单。 验证后,我将表单数据保存在一个表中,更新另外 2 个表,发送一封电子邮件并将用户重定向到另一个确认页面。

它可以工作,但在某些情况下可能会很慢。 而在这些情况下,我曾经历过用户再次点击的情况。这样做会再次发送表单数据,但表单验证失败(防止重复的正常行为)但用户永远不会重定向到确认页面,这是有问题的。

要解决这个问题,我想:

  1. 防止用户点击两次弹出按钮(第一次点击后禁用)
  2. 在我看来改进数据处理
  3. 改进我的逻辑

对于第一点,我必须使用JS,对吗? 对于第二点,由于 2 个表是更新的,我认为使用更新会更好 第三个,?

谢谢你的建议

def randomisation_edit(request):

    if request.method == "POST":
        form = RandomisationForm(request, data=request.POST or None)
        if form.is_valid():
            randomisation = form.save()
            pays = randomisation.ran_num[0:3].upper()
            centre = randomisation.ran_num[4:6].upper()
            status = randomisation.ran_vih
            severity = randomisation.ran_sta
            rand = Randomiser(pays, centre, status, severity)
 
            # Mise à jour de la base de données -> Patient code pour rendre indisponible la ligne
            # pour une prochaine randomisation

            # ListeRandomisation
            # 1.Récupération de la ligne dans la liste de rando
            bras = rand['bras']

            # 2.Mise à jour de la ligne dans la liste de rando
            patient = get_object_or_404(ListeRandomisation, ran_ide = bras)
            patient.pat = randomisation.ran_num # pat
            patient.save()

            # Medicament
            # 1.Récupération de la ligne dans la liste de correspondance médicament
            medicament = rand['medicament']

            # 2.Mise à jour de la ligne dans la liste de correspondance médicament
            medicament = get_object_or_404(Medicament, med_ide = medicament)
            medicament.pat = randomisation.ran_num # pat
            medicament.save()

            pays = randomisation.ran_num[0:3].upper()
            centre = randomisation.ran_num[4:6].upper()
            request.session['can_randomize'] = is_randomizable(pays, centre)

            # 3. Mise à jour de la table Randomisation avec le bras et le numéro de boite attribués
            randomisation.ran_bra = patient.ran_bra
            randomisation.ran_med = medicament.med_num
            randomisation.ran_log_dat = timezone.now() # datetime.now(timezone.utc)
            randomisation.ran_log = request.user.username
            # randomisation.ran_log_sit = request.session.get('selected_site') 
            randomisation.ran_log_sit = request.session.get('user_site')
            randomisation.save()

            email('randomisation',randomisation.ran_num,randomisation.ran_bra,medicament.med_num,'',randomisation.ran_log,patient.ran_ide,medicament.med_ide,randomisation.ran_vih,randomisation.ran_sta)

            return redirect('randomization:confirmation', pk = randomisation.pk)

    else:
        form = RandomisationForm(request)

    return render(request, 'randomization/randomisation_edit.html', {'form': form})

【问题讨论】:

    标签: python django


    【解决方案1】:

    用 Django 做这件事似乎有点多,我觉得这个问题最好在前端处理。我们可以使用 Jquery 来禁用我们的按钮,这应该可以消除您遇到的任何错误。

    我们将首先引用我们的表单#myForm,提交后,将我们的属性设置为disabled

    $('#myForm').one('submit', function() {
        $(this).find('input[type="submit"]').attr('disabled','disabled');
    }); 
    

    【讨论】:

      【解决方案2】:

      我更喜欢以后端方式做事,因为与前端不同,它不容易被绕过。 所以我发现Django Rate limit 相当简单。

      它存储用户特定的值,例如 IP 地址,以便在第一个请求到达时立即缓存。因为缓存真的很快,所以在第二次点击发生之前会有一个值阻止同一个用户执行相同的功能。

      • pip install django-ratelimit

      从 ratelimit.decorators 导入 ratelimit

      @ratelimit(key='ip')
      def myview(request):
          # ...
      
      @ratelimit(key='ip', rate='100/h')
      def secondview(request):
          # ...
      

      【讨论】:

      • 感谢两位。前端做的伎俩,但我会测试后端解决方案
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-25
      • 1970-01-01
      • 2013-05-18
      • 2020-06-11
      • 1970-01-01
      • 2014-11-13
      相关资源
      最近更新 更多