2010-01-26 12 views
17

मैं उपयोगकर्ताओं को अपने रूपों को दोबारा सबमिट करने से रोकने के लिए एक रास्ता खोजने की कोशिश कर रहा हूं। मेरे पास जावास्क्रिप्ट है जो सबमिट बटन को अक्षम करता है, लेकिन अभी भी एक प्रासंगिक उपयोगकर्ता है जो डबल-सबमिट करने का तरीका ढूंढता है।क्या डुप्लिकेट फॉर्म सबमिशन को रोकने के लिए लाइब्रेरी django के लिए मौजूद है?

मेरे पास एक पुनः उपयोग करने योग्य लाइब्रेरी का एक दृष्टिकोण है जिसे मैं इससे बचाने के लिए बना सकता हूं।

मेरी आदर्श पुस्तकालय में, कोड ब्लॉक कुछ इस तरह दिखेगा:

duplicate_submission_locks

  • submission_hash # के MD5:

    try: 
        with acquire_lock({'field1':'abc', 'field2':'def'}) as lock: 
         response = #do some credit card processing 
         lock.response = response 
    except SubmissionWasDuplicate, e: 
        response = e.response 
    

    ताला तालिका कुछ इस तरह दिखेगा सबमिट किए गए तर्क

  • प्रतिक्रिया # मसालेदार डेटा
  • created_at इस तालिका व्यापक के लिए इस्तेमाल किया #
  • lock_expired # बूलियन वाचक अगर ताला

किसी को भी पता है कि अगर यह पहले से मौजूद है समाप्त हो गया है? ऐसा लिखना मुश्किल नहीं लगता है, इसलिए यदि यह अस्तित्व में नहीं है तो मैं इसे स्वयं लिख सकता हूं।

+0

इस सवाल http पर एक नज़र डालें: // stackoverflow। कॉम/प्रश्न/320096/django-how-can-i-protect-against-concurrent-modification-of-data-base-प्रविष्टियों में ऑप्टिस्टिक लॉक –

+0

के बारे में कुछ अच्छे विचार हैं आशावादी लॉक मुझे जो चाहिए, उसके करीब है बातें। 1) यह एक साइनअप फॉर्म पर है इसलिए अभी तक अपडेट करने के लिए मॉडल फ़ील्ड नहीं है। 2) यदि यह एक डबल-सबमिट है, तो मैं चाहता हूं कि दोनों सबमिशन सफल पृष्ठ या फिर से प्रयास करें जो उचित होगा। – Gattster

उत्तर

6

इस समस्या का एक आसान समाधान प्रत्येक रूप में एक अद्वितीय हैश जोड़ना है। फिर आप वर्तमान रूपों की एक रोलिंग टेबल हो सकती है। जब कोई फॉर्म सबमिट किया जाता है, या हैश बहुत पुराना हो जाता है, तो आप इसे अपनी तालिका से समाप्त कर सकते हैं, और किसी भी फॉर्म को अस्वीकार कर सकते हैं जिसमें आपकी तालिका में कोई मिलान हैश नहीं है।

HTTPRedirect पहले उल्लेख किया गया है, ऐसा करने का सही तरीका है।

दुर्भाग्यवश, यहां तक ​​कि Django के स्वयं के व्यवस्थापक में भी इस मुद्दे से संबंधित समस्याओं का सामना करना पड़ता है। कुछ मामलों में, क्रॉस-साइट स्क्रिप्टिंग फ्रेमवर्क इनमें से कुछ को रोकने में सहायता कर सकता है, लेकिन मुझे डर है कि वर्तमान उत्पादन संस्करणों में यह अंतर्निहित नहीं है।

+0

मुझे आश्चर्य है कि अगर उपयोगकर्ता अपने बैक-बटन का उपयोग करता है और अलग-अलग फ़ील्ड के साथ उसी फॉर्म को पुनः सबमिट करता है तो यह ग्लिच हिट करेगा? हमें अद्वितीय हैश रीफ्रेश करने की आवश्यकता होगी। – Gattster

+0

आपका अनुरोध पुनर्वितरण को रोकने के लिए था। डीबी से हैश को हटाने से वह आसानी से ऐसा करना चाहिए। कुछ अलग-अलग मूल्यों के साथ सबमिट किया गया एक फॉर्म अभी भी ज्यादातर मामलों में पुनः प्रस्तुत करना है, हालांकि आप हैश का उपयोग अस्थायी अग्रेषित संदर्भ को जमा करने के लिए कर सकते हैं, जो कि कुछ सीमित अवधि के लिए पिछले सबमिशन को संपादित करने की इजाजत देता है। –

4

ईमानदार होने के लिए, आपका सर्वोत्तम शर्त (आसान और अच्छी प्रैक्टिस) धन्यवाद पृष्ठ पर HTTPRedirect() जारी करना है, और यदि धन्यवाद पृष्ठ फॉर्म के समान ही है, तो यह ठीक है। आप अभी भी ऐसा कर सकते हैं।

+0

उत्तर देने के लिए धन्यवाद। धन्यवाद पृष्ठ प्रदर्शित करने के लिए HTTPRedirect करना मेरे मन में था। यह प्रश्न यह पता लगाने के बारे में अधिक है कि पोस्ट डुप्लिकेट है। – Gattster

2

रीडायरेक्ट का उपयोग करना हमेशा अच्छा होता है -पोस्ट विधि। यह उपयोगकर्ता को ब्राउज़र से रीफ्रेश फ़ंक्शन का उपयोग करके फ़ॉर्म को गलती से पुनः सबमिट करने से रोकता है। जब भी हैश विधि का उपयोग करते हैं तब भी यह सहायक होता है। ऐसा इसलिए है क्योंकि पोस्ट के बाद रीडायरेक्ट किए बिना, बैक/रिफ्रेश बटन मारने के मामले में, उपयोगकर्ता को फ़ॉर्म को पुनः सबमिट करने के बारे में एक प्रश्न संदेश दिखाई देगा, जो उसे भ्रमित कर सकता है।

यदि आप प्रत्येक पोस्ट के बाद एक जीईटी रीडायरेक्ट करते हैं, तो बैक/रिफ्रेश को मारना इस wierd (सामान्य उपयोगकर्ता के लिए) संदेश प्रदर्शित नहीं करेगा। तो पूर्ण सुरक्षा के लिए हैश + रीडायरेक्ट-पोस्ट-पोस्ट का उपयोग करें।

10

आप हैश

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

इस दृष्टिकोण के साथ (सत्र कुकी को हटाने नहीं) उपयोगकर्ता नहीं डेटा को फिर से स्टोर कर सकते हैं util सत्र समाप्त हो, वैसे स्टोर करने के लिए एक सत्र का उपयोग कर सकते, मैं मुझे लगता है कि ऐसा कुछ मौजूद है जो उपयोगकर्ता को पहचानता है जो

+0

क्या होता है यदि उपयोगकर्ता/धन्यवाद/पृष्ठ हिट करता है और लेनदेन अभी तक समाप्त नहीं हुआ है? इसके अलावा, लेनदेन विफल होने पर क्या होगा? – Gattster

+1

यदि लेनदेन विफल रहता है, तो आपको सत्र समाप्त करना होगा और कुछ त्रुटि पृष्ठ पर रीडायरेक्ट करना होगा। यदि आप आश्वस्त करना चाहते हैं कि लेनदेन पूर्ण होने पर केवल "/ धन्यवाद" पृष्ठ पर जा सकता है, तो लेन-देन पूरा होने पर उसे टोकन जोड़ना होगा और इसे "/ धन्यवाद" पृष्ठ पर भेजना होगा और वहां सत्यापित किया जाएगा (जैसे पेपैल करता है) –

3

क्रिस्टियन डेमियन का जवाब वास्तव में एक महान सुझाव है। मैंने बस उस विषय पर थोड़ी भिन्नता के बारे में सोचा, लेकिन यह अधिक ओवरहेड हो सकता है।

आप कुछ है कि BaseHandler वस्तुओं, जो एक विधि exists() कहा जाता है, तो क्या आप सबमिट कर रहे हैं डेटाबेस में पहले से ही है देखने के लिए जाँच करता है वह यह है कि के लिए django-piston में प्रयोग किया जाता है को लागू करने की कोशिश कर सकते।

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 

तो चलो का कहना है कि एक समारोह request_exists() कहा जाता है बनाते हैं, एक विधि के बजाय:

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

यह काम करेगा। मेरे लिए यह मुख्य सवाल यह है कि डुप्ली सबमिशन को गहन तरीके से कैसे संभालना है। चूंकि पहली सबमिशन शायद अभी तक समाप्त नहीं हुई है, इसलिए मुझे पहले सबमिशन समाप्त होने तक देरी की आवश्यकता है। तो मुझे उपयोगकर्ता को धन्यवाद पृष्ठ पर भेजने की आवश्यकता है और सबमिशन का परिणाम मिलना है, जो एक त्रुटि संदेश के साथ सफल हो सकता है या विफल हो सकता है। – Gattster

+0

ठीक है आपको उन्हें नग्न "/ धन्यवाद /" पृष्ठ पर भेजने की ज़रूरत नहीं है। आप इसे अनुरोध डेटा के साथ भेज सकते हैं ताकि टेम्पलेट सबमिशन के परिणामों को संसाधित करने में सक्षम हो और उन्हें तदनुसार प्रदर्शित कर सके। "/ धन्यवाद /" पहुंचने से पहले शायद एक अंतरालीय "/ add/confirm /" पृष्ठ अच्छा होगा? – jathanism

संबंधित मुद्दे