2010-07-12 79 views
12

我做錯了什麼,或者是這個認真什麼開發人員希望我寫每次我想檢查兩個字段是否相同?爲什麼要檢查Django中的兩個密碼匹配如此複雜?

def clean(self): 
    data = self.cleaned_data 
    if "password1" in data and "password2" in data: 
     if data["password1"] != data["password2"]: 
      self._errors["password2"] = self.error_class(['Passwords do not match.']) 
      del data['password2']  
    return data 

爲什麼我必須驗證用戶名是否唯一?

def clean_username(self): 
    data = self.cleaned_data['username'] 
    if User.objects.filter(username=data).exists(): 
     raise ValidationError('Username already taken.') 
    return data 

這是一個ModelForm。它應該已經知道有一個獨特的約束?

回答

26

這裏是我會做:

這是唯一的清潔方法您需要定義以確保2個密碼正確且用戶名有效。

使用clean_fieldname方法,以便您無需執行更多工作來驗證用戶名。

def clean_password2(self): 
    password1 = self.cleaned_data.get('password1') 
    password2 = self.cleaned_data.get('password2') 

    if not password2: 
     raise forms.ValidationError("You must confirm your password") 
    if password1 != password2: 
     raise forms.ValidationError("Your passwords do not match") 
    return password2 

你是絕對正確的,你需要驗證用戶名是唯一的,因爲的ModelForm知道它必須是唯一的。

您的代碼存在的問題是您正在覆蓋clean()方法,這意味着ModelForm未執行其「真正的」clean()。

要獲得默認驗證,請致電super(MyForm, self).clean()或更好,但不要覆蓋clean,只能指定clean_password2

+0

我想這是我最終得出的結論,謝謝。忘了這個問題:) – mpen 2010-12-18 03:10:54

+0

ooops,我沒有意識到這是如此之舊:D – 2010-12-18 04:48:36

+0

仍然很好,你回答它:) – GreenAsJade 2014-11-29 05:25:16

1

您可能需要爲第一個if添加else:部件。目前該函數返回data,即使其中一個密碼不存在,也不會設置任何錯誤 - 是否爲預期行爲?

else: 
    self._errors["password"] = self.error_class(['One or both of the passwords not found']) 

if "password1" in data and "password2" in data:這確保兩個密碼都存在。如果沒有這一行,您會在下一行讀到data[password1]data[password2](如果其中任何一個不存在),就會出錯。

接下來的三行比較密碼並設置相應的錯誤消息 - 這是必需的,不是嗎?

正如他們所說,讓事情儘可能簡單,而不是現在。

+0

我不*認爲*這是必要的......如果任一密碼不存在,這意味着已經有錯誤,不是嗎?我真的不需要再投第二個。是的,這可能會變得更簡單。定義字段時,我寫'password2 = PasswordField(validate = EqualTo('password1'))'?它應該能夠找出其餘的。 – mpen 2010-07-12 06:21:57

4

首先,你是否認爲抱怨四行鍋爐板碼?如果真的困擾你,創建一個PasswordForm類包含乾淨的邏輯,並根據需要爲你自己的表單分類。

其次,你不需要必須手動驗證唯一約束。正如你所說,ModelForm爲你做到了。評論

這種「怪異語法」後

編輯是因爲檢查兩個密碼字段匹配是不同的流量比事物的正常計劃。首先,您要檢查主要的clean方法,而不是特定字段clean_myfield。如果它是後者,你只會引發異常,Django確實會刪除字段數據。

所以,不,這是每個表格上沒有7號線 - 看到我的子類注 - 這肯定不是7系倍多領域的,因爲你不希望其他任何類型的做到這一點的領域。

+0

那麼有些東西搞砸了,因爲我剛剛得到一個重複的關鍵錯誤。我只是想婊子,因爲我厭倦了這個項目:( – mpen 2010-07-12 06:38:39

+0

它是7行...怪異的語法。爲什麼我必須檢查數據是否在字典中,然後刪除它?Isn那是一個奇怪的設計嗎?已經有一個錯誤列表,它可以檢查是否想知道是否有錯誤,而且我應該能夠追加另外一個,而不是真的關心它已經出錯了。然後爲什麼要返回數據呢?我已經在操作self.cleaned_data了,看起來沒有必要返回任何東西。如果他們通過了字典,那麼也許。 – mpen 2010-07-12 06:45:17

+0

而且它甚至不僅僅是7行。它在每一個奇怪的表單上有7行,乘以幾個字段 – mpen 2010-07-12 06:45:59

4

http://k0001.wordpress.com/2007/11/15/dual-password-field-with-django/


編輯:找到出路有問題的管理形式的交易:http://code.djangoproject.com/svn/django/trunk/django/contrib/auth/forms.py

class AdminPasswordChangeForm(forms.Form): 
    """ 
    A form used to change the password of a user in the admin interface. 
    """ 
    password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput) 
    password2 = forms.CharField(label=_("Password (again)"), widget=forms.PasswordInput) 

    def __init__(self, user, *args, **kwargs): 
     self.user = user 
     super(AdminPasswordChangeForm, self).__init__(*args, **kwargs) 

    def clean_password2(self): 
     password1 = self.cleaned_data.get('password1') 
     password2 = self.cleaned_data.get('password2') 
     if password1 and password2: 
      if password1 != password2: 
       raise forms.ValidationError(_("The two password fields didn't match.")) 
     return password2 

    def save(self, commit=True): 
     """ 
     Saves the new password. 
     """ 
     self.user.set_password(self.cleaned_data["password1"]) 
     if commit: 
      self.user.save() 
     return self.user 
相關問題