2010-05-06 78 views
0

爲了避免垃圾郵件,我想增加一個等待時間來重新提交表格(即用戶應該等待幾秒鐘提交表格,,除了第一次提交此表格提交)。如何構建需要延遲重新提交的Django表單?

爲此,我在表單中添加了一個timestamp(以及一個包含時間戳記的security_hash字段加上settings.SECRET_KEY,這確保了時間戳不被弄亂)。這看起來像:

class MyForm(forms.Form): 
    timestamp  = forms.IntegerField(widget=forms.HiddenInput) 
    security_hash = forms.CharField(min_length=40, max_length=40, widget=forms.HiddenInput) 
    # + some other fields.. 

    # + methods to build the hash and to clean the timestamp... 
    # (it is based on django.contrib.comments.forms.CommentSecurityForm) 

    def clean_timestamp(self): 
     """Make sure the delay is over (5 seconds).""" 
     ts = self.cleaned_data["timestamp"] 
     if not time.time() - ts > 5: 
      raise forms.ValidationError("Timestamp check failed") 
     return ts 

    # etc... 

這工作正常。但是仍然存在一個問題:時間戳是在用戶首次提交表單時檢查的,我需要避免這種情況

任何想法解決它?

謝謝! :-)

+0

你爲什麼不在用戶的會話中記錄這個? – 2010-05-06 20:48:25

+0

我認爲會議也是要走的路。 – Dingle 2010-05-06 22:26:33

回答

2

一種方式是一個initial值設置爲時間,比方說0,一旦形式驗證其更新爲當前的時間戳,並且只檢查時間戳時,它不是0:

class MyForm(forms.Form): 
    timestamp  = forms.IntegerField(widget=forms.HiddenInput, initial=0) 
    #look at the initial = 0 

    security_hash = forms.CharField(min_length=40, max_length=40, widget=forms.HiddenInput) 


    def clean_timestamp(self): 
     """Make sure the delay is over (5 seconds).""" 
     ts = self.cleaned_data["timestamp"] 
     if timestamp != 0 and not time.time() - ts > 5: 
      raise forms.ValidationError("Timestamp check failed") 
     return ts 

    def clean(self): 
     cleaned_data = self.cleaned_data 
     if len(self._errors) == 0: #it validates 
      cleaned_data["timestamp"] = time.time() 
     return cleaned_data 

另一種可能的解決方案是使用sessions。它更安全但不是防彈。用以前的應用程序,用戶可以多次發送相同的發佈數據,並且表單將多次驗證(因爲他發送相同的時間戳)。通過會話,您需要用戶啓用Cookie,但他們將無法發送驗證時間超過5秒的發佈數據。

這樣一旦正確的表單提交發生,您可以將時間保存在用戶的會話密鑰中,並在重新驗證表單之前檢查該時間。這很容易在視圖中完成。如果您想在表單邏輯級別執行此操作,則需要在接受請求的表單中創建您自己的清理方法(以便您可以使用會話)。要小心,用戶可以清理他的cookies並作爲「新」用戶發佈。

希望這會有所幫助。

+0

我沒有考慮使用用戶的會話。謝謝 :-) – user176455 2010-05-08 14:51:55

2

第一次檢查時間戳是用戶提交表單時,我需要避免這種情況。

如果這是問題,難道你不能創建窗體設置時間戳-5分鐘嗎?要做到這一點