Django密码和确认密码验证

8

我在验证同一个表单中的两个字段(密码和密码确认)时遇到了一些问题。

问题在于,当我使用我创建的方法验证密码后,当我尝试验证密码确认时,我不再能够访问这个变量,password = self.cleaned_data['password'] 变成了 'None'

class NewAccountForm(forms.Form):

password =  forms.CharField(widget=forms.PasswordInput(attrs={'class': 'narrow-input', 'required': 'true' }), required=True, help_text='Password must be 8 characters minimum length (with at least 1 lower case, 1 upper case and 1 number).')
password_confirm = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'narrow-input', 'required': 'true' }), required=True, )

def __init__(self, *args, **kwargs):
    super(NewAccountForm, self).__init__(*args, **kwargs)
    self.fields['password'].label = "Password"
    self.fields['password_confirm'].label = "Password Confirmation"

"

密码验证" <- 这个验证已经生效。

"
def clean_password(self):
    validate_password_strength(self.cleaned_data['password'])

由于密码为“None”,因此未正确执行第二个验证:

def clean_password_confirm(self):
    password = self.cleaned_data['password']
    password_confirm = self.cleaned_data.get('password_confirm')

    print(password)
    print(password_confirm)
    if password and password_confirm:
        if password != password_confirm:
            raise forms.ValidationError("The two password fields must match.")
    return password_confirm

如果第一种方法(clean_password)已经验证了密码字段的输入,是否有办法将其作为变量用于第二个验证方法(clean_password_confirm)?

谢谢。

编辑:更新版本:

def clean(self):
    cleaned_data = super(NewAccountForm, self).clean()
    password = cleaned_data.get('password')

    # check for min length
    min_length = 8
    if len(password) < min_length:
        msg = 'Password must be at least %s characters long.' %(str(min_length))
        self.add_error('password', msg)

    # check for digit
    if sum(c.isdigit() for c in password) < 1:
        msg = 'Password must contain at least 1 number.'
        self.add_error('password', msg)

    # check for uppercase letter
    if not any(c.isupper() for c in password):
        msg = 'Password must contain at least 1 uppercase letter.'
        self.add_error('password', msg)

    # check for lowercase letter
    if not any(c.islower() for c in password):
        msg = 'Password must contain at least 1 lowercase letter.'
        self.add_error('password', msg)

    password_confirm = cleaned_data.get('password_confirm')


    if password and password_confirm:
        if password != password_confirm:
            msg = "The two password fields must match."
            self.add_error('password_confirm', msg)
    return cleaned_data
1个回答

9

您可以在clean()方法中测试多个字段。

例如:

def clean(self):
    cleaned_data = super(NewAccountForm, self).clean()

    password = cleaned_data.get('password')
    password_confirm = cleaned_data.get('password_confirm ')

    if password and password_confirm:
        if password != password_confirm:
            raise forms.ValidationError("The two password fields must match.")
    return cleaned_data

请参阅有关清理和验证相互依赖字段的文档。


感谢您的帮助。阅读文档后,我重写了该方法,并使用clean()函数。我编辑了我的问题以展示这些更改后的代码。如果您能提出任何改进意见,我将不胜感激。另外,作为对您答案的建议,我只会修改返回语句为“return cleaned_data”。 - revy
谢谢您的建议,确实是个打字错误。您的新代码有效,对吗?如果无效,请开一个新问题。 - SaeX
这确实是正确的答案,但我如何在不覆盖clean方法的情况下实现呢?我的意思是,当我们从django-admin创建新用户时,它们具有相当好的密码强度验证器,我希望在我的表单中使用所有这些验证器,而不需要覆盖clean或clean_*方法。 - AgentNirmites

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接