Py学习  »  Django

为什么在Django检查两个密码是否匹配如此复杂?

Mark • 5 年前 • 1130 次点击  

是我做错了什么,还是这个? 认真地 每当我想检查两个字段是否相同时,开发人员希望我编写什么?

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 . 它应该已经知道有一个独特的约束?

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/30344
 
1130 次点击  
文章 [ 4 ]  |  最新文章 5 年前
Amarghosh
Reply   •   1 楼
Amarghosh    13 年前

您可能需要添加 else: 第一部分 if . 当前函数返回 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] 如果他们中的任何一个不在场。

接下来的三行比较密码并设置适当的错误消息——这是必需的,不是吗?

正如他们所说,使事情尽可能简单,不再是。

StefanNch
Reply   •   2 楼
StefanNch    13 年前

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
Daniel Roseman
Reply   •   3 楼
Daniel Roseman    13 年前

首先,你是 认真地 抱怨四行炉号?如果它真的困扰你,创建一个 PasswordForm 类,它包含干净的逻辑,并根据需要为您自己的窗体子类。

其次,你 不要 必须手动验证唯一约束。正如您所说,ModelForm为您完成了这项工作。

评论后编辑

这种“奇怪的语法”是因为检查两个密码字段是否匹配是 不同流量 比正常情况下的情况要好。首先,你要检查主系统 clean 方法而不是字段特定的 clean_myfield . 如果是后者,只需引发一个异常,Django确实会删除字段数据。

所以不,这不是每个表单上的7行-参见我关于子类化的注释-而且它 当然 不是7行乘以多个字段,因为您不想对任何其他类型的字段执行此操作。

Yuji 'Tomita' Tomita
Reply   •   4 楼
Yuji 'Tomita' Tomita    13 年前

我要做的是:

这是唯一需要定义的干净方法,以确保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没有执行其“real”clean()。

要获取默认验证,请调用 super(MyForm, self).clean() 或者最好还是不要重写 clean 一点也不例外 clean_password2 .