Does a library to prevent duplicate form submissions exist for django?

前端 未结 5 501
悲&欢浪女
悲&欢浪女 2020-12-06 04:55

I am trying to find a way to prevent users from double-submitting my forms. I have javascript that disables the submit button, but there is still an occasional user who fin

相关标签:
5条回答
  • 2020-12-06 05:31

    One easy solution to this problem is to add a unique hash to each form. Then you can have a rolling table of current forms. When a form is submitted, or the hash gets too old, you can expire it out of your table, and reject any form which does not have a matching hash in your table.

    The HTTPRedirect is the correct way to do it, as previously mentioned.

    Unfortunately, even Django's own built in admin is prone to problems related to this issue. In some cases, the cross-site scripting framework can assist to prevent some of this, but I'm afraid the current production versions just don't have this built in.

    0 讨论(0)
  • 2020-12-06 05:32

    It is always good to use the redirect-after-post method. This prevents user from accidently resubmitting the form using refresh function from the browser. It is also helpful even when you use the hash method. It's because without redirect after a POST, in case of hitting Back/Refresh button, user will see a question message about resubmitting the form, which can confuse her.

    If you do a GET redirect after every POST, then hitting Back/Refresh won't display this wierd (for usual user) message. So for full protection use Hash+redirect-after-post.

    0 讨论(0)
  • 2020-12-06 05:34

    You can use a session to store the hash

    import hashlib
    
    def contact(request):
        if request.method == 'POST':
            form = MyForm(request.POST)
            #join all the fields in one string
            hashstring=hashlib.sha1(fieldsstring)
            if request.session.get('sesionform')!=hashstring:
                if form.is_valid() :                                         
                    request.session['sesionform'] = hashstring
                    #do some stuff...
                    return HttpResponseRedirect('/thanks/') # Redirect after POST  
            else
               raise SubmissionWasDuplicate("duplicate")
        else:
            form = MyForm() 
    

    With this approach (not deleting the session cookie) the user can't re-store the data util the session expires, by the way, i'm assuming that exist something who identify the user who send the data

    0 讨论(0)
  • 2020-12-06 05:36

    To be honest, your best bet (easy and good practice) is to issue a HTTPRedirect() to the thank you page, and if the thank you page is the same one as the form, that's OK. You can still do this.

    0 讨论(0)
  • 2020-12-06 05:37

    Kristian Damian's answer is really a great suggestion. I just thought of a slight variation on that theme, but it might have more overhead.

    You could try implementing something that is used in django-piston for BaseHandler objects, which is a method called exists() that checks to see if what you are submitting is already in the database.

    From handler.py (BaseHandler):

    def exists(self, **kwargs):
        if not self.has_model():
            raise NotImplementedError
    
        try:
            self.model.objects.get(**kwargs)
            return True
        except self.model.DoesNotExist:
            return False
    

    So let's say make that a function called request_exists(), instead of a method:

    if form.is_valid()
        if request_exists(request):
            # gracefully reject dupe submission
        else:
            # do stuff to save the request
            ...
            # and ALWAYS redirect after a POST!!
            return HttpResponseRedirect('/thanks/') 
    
    0 讨论(0)
提交回复
热议问题