【问题标题】:prevent multiple submissions when user clicks submit button multiple times before loading to the new page当用户在加载到新页面之前多次单击提交按钮时,防止多次提交
【发布时间】:2016-02-11 05:38:13
【问题描述】:

我用谷歌搜索了一下,似乎 php 有很多可能性。但我还没有为 django 找到任何好的解决方案。我看到有些人为此使用客户端javascript代码,但我只是不知道如何解决这个问题。我遇到的问题是:当用户写一篇文章时,在新页面加载之前快速单击提交按钮两次,然后将发布两篇文章。这是我的代码,在此先感谢。 我的html

<form id="post_form" method="post" action="/add_post/" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form|crispy }}
<input type="submit" name="submit" value="submit">
</form>

我的意见.py

class PostCreateView(CreateView):

    model = Post
    form_class = PostForm
    template_name = 'main/add_post.html'

    def form_valid(self, form):

        self.object = form.save(commit=False)
        # any manual settings go here

        #self.object.category = Category.objects.filter(category__in=categories).all()

        self.object.moderator = self.request.user
        self.object.image = extract(self.object.url) 
        self.object.thumbnail = extractt(self.object.content)
        self.object.save()
        return HttpResponseRedirect(reverse('post', args=[self.object.slug]))

    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        return super(PostCreateView, self).dispatch(request, *args, **kwargs)       

编辑:我把它改成了这样

{% block content %}
<div class="col-sm-5">
<form id="post_form" method="post" action="/add_post/" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form|crispy }}
<input type="submit" id="button" name="submit" value="올리기">
</form>
</div>
<div class="col-sm-4" style="width:400px; height:250px; border:1px solid black;">
<h3>rule</h3>

</div>

<div class="col-sm-3" style="width:420px; height:750px; border:1px solid black;" >
<h3>ad</h3>
</div>
    {% endblock %}
<script>
    jQuery('input[name=submit]').on('click', function(){
 if(jQuery(this).hasClass('active')){
   return false;
 }
 else{
  jQuery(this).addClass('active');
 }
});
    </script>
   {% include 'footer.html' %}

最终编辑:希望这是对的吗?有什么建议吗?

import datetime

class PostCreateView(CreateView):

    model = Post
    form_class = PostForm
    template_name = 'main/add_post.html'

    def form_valid(self, form):

        self.object = form.save(commit=False)
        # any manual settings go here

        #self.object.category = Category.objects.filter(category__in=categories).all()

        self.object.moderator = self.request.user
        self.object.image = extract(self.object.url) 
        self.object.thumbnail = extractt(self.object.content)
        self.object.save()

        if not hasattr(self.request.session['last_submitted']):
            self.request.session['last_submitted'] = datetime.datetime.now()
            return HttpResponseRedirect(reverse('post', args=[self.object.slug]))
        else:
            delta = datetime.datetime.now() - self.request.session['last_submitted']
            if delta.seconds < 60: # assume allow re-submit after 60 seconds
                return http.HttpForbidden() #or some other better message??
            else:
                return HttpResponseRedirect(reverse('post', args=[self.object.slug]))

    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        return super(PostCreateView, self).dispatch(request, *args, **kwargs) 

使用提供的解决方案进行编辑

class PostCreateView(CreateView):

     model = Post
     form_class = PostForm
     template_name = 'main/add_post.html'

     def form_valid(self,form):

        if not hasattr(self.request.session['last_submitted']):
            last_submitted = pickle.dumps(datetime.datetime.now())
            self.request.session['last_submitted'] = last_submitted
            save_it = True
        else:
            last_submitted = pickle.loads(self.request.session['last_submitted'])
            delta = datetime.datetime.now() - last_submitted
            save_it = (delta.seconds > 60) # assume allow re-submit after 60 seconds

        if save_it:
          self.object = form.save(commit=False)
          # any manual settings go here

          #self.object.category =      Category.objects.filter(category__in=categories).all()

          self.object.moderator = self.request.user
          self.object.image = extract(self.object.url) 
          self.object.thumbnail = extractt(self.object.content)
          self.object.save()
          return HttpResponseRedirect(reverse('post', args=[self.object.slug]))
        else:
           # consider redirect as usual, if the user just clicked twice by mistake
           return self.form_invalid(form) # or Http error code

【问题讨论】:

    标签: javascript python django


    【解决方案1】:

    如果这是按钮:

    <input type="submit" name="submit" value="submit" id="preventDouble">
    

    使用 jQuery:

    $("#preventDouble").on("submit",function(){
        $(this).unbind("submit");
        $(this).on("submit",function(){return false;});
    };
    

    在第一次提交之后,jQuery 会附加一个取消进一步提交的事件。

    请注意,此事件不检查表单是否实际成功提交到服务器。

    这可能会回答您的问题,但它是一种更安全、更好的方法来跟踪服务器上的多个提交,例如向会话添加“last_submitted”属性,如果 datetime.datetime.now 距离 session.last_submitted 不到 1 分钟,则阻止进一步提交:

    import datetime
    import pickle
    
    def form_valid(self,form):
    
        if not hasattr(self.request.session['last_submitted']):
            last_submitted = pickle.dumps(datetime.datetime.now())
            self.request.session['last_submitted'] = last_submitted
            save_it = True
        else:
            last_submitted = pickle.loads(self.request.session['last_submitted'])
            delta = datetime.datetime.now() - last_submitted
            save_it = (delta.seconds > 60): # assume allow re-submit after 60 seconds
    
        if save_it:
          self.object = form.save(commit=False)
          # any manual settings go here
    
          #self.object.category =      Category.objects.filter(category__in=categories).all()
    
          self.object.moderator = self.request.user
          self.object.image = extract(self.object.url) 
          self.object.thumbnail = extractt(self.object.content)
          self.object.save()
          return HttpResponseRedirect(reverse('post', args=[self.object.slug]))
        else:
           # consider redirect as usual, if the user just clicked twice by mistake
           return self.form_invalid(form) # or Http error code      
    

    编辑

    import datetime
    import pickle
    
    class PostCreateView(CreateView):
    
         model = Post
         form_class = PostForm
         template_name = 'main/add_post.html'
    
         def form_valid(self,form):
    
            if not hasattr(self.request.session['last_submitted']):
                last_submitted = pickle.dumps(datetime.datetime.now())
                self.request.session['last_submitted'] = last_submitted
                save_it = True
            else:
                last_submitted = pickle.loads(self.request.session['last_submitted'])
                delta = datetime.datetime.now() - last_submitted
                save_it = (delta.seconds > 60) # assume allow re-submit after 60 seconds
    
            if save_it:
              self.object = form.save(commit=False)
              # any manual settings go here
    
              #self.object.category =      Category.objects.filter(category__in=categories).all()
    
              self.object.moderator = self.request.user
              self.object.image = extract(self.object.url) 
              self.object.thumbnail = extractt(self.object.content)
              self.object.save()
              return HttpResponseRedirect(reverse('post', args=[self.object.slug]))
            else:
               # consider redirect as usual, if the user just clicked twice by mistake
               return self.form_invalid(form) # or Http error code
    

    【讨论】:

    • 嗯我同意你的看法,这可能是最好的方法。限制用户试图在一分钟内发布超过一个....你知道怎么做吗?顺便谢谢你的想法:)
    • 嗯,对不起,我是个菜鸟……(这是我的第一个项目)。只是为了确保代码进入我的 views.py 类 PostCreateView(CreateView) 所在的位置??
    • 是的。 continue 通常是 form.save(),reject 是要发送给用户的一些消息
    • 嗨,嗯,我最后的方法是我在那里编辑的,你介意看看这个吗?
    • 更新了答案。请注意,您可能希望在第二次提交后 Httpredirect 没有错误,如果用户两次提交错误,那么您只需忽略它并照常重定向
    【解决方案2】:

    不确定您的项目是否使用 jquery lib。如果确实尝试以下操作:

    jQuery('input[name=submit]').on('click', function(){
     if(jQuery(this).hasClass('active')){
       return false;
     }
     else{
      jQuery(this).addClass('active');
     }
    });
    

    这将检查按钮是否已被点击。如果是,则不会重新提交该页面。 如果您没有使用任何客户端库,那么我可以将其更改为 Native js。

    【讨论】:

    • 您好,谢谢。是的,我在我的项目中使用 jquery。但是我对js和jquery不是很熟悉。我马上试试,谢谢
    • 所以,我尝试将您的代码放在我的 html 文件中,在 之间。但这行不通……我做错了吗?
    • 一旦你的页面被加载,尝试在浏览器控制台中运行它。然后尝试单击按钮。它会给你一个想法,如果它有效。它可能需要 dom 就绪功能。在控制台中尝试一次。
    • 我一定是做错了什么.....我没有收到任何错误,或者它正在做我想要的错误
    • 运行代码后你仍然看到多个post请求?
    猜你喜欢
    • 2016-05-23
    • 2019-06-24
    • 1970-01-01
    • 2014-11-29
    • 1970-01-01
    • 1970-01-01
    • 2018-10-07
    • 1970-01-01
    • 2015-07-11
    相关资源
    最近更新 更多