2010-07-12 46 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