【问题标题】:Conditional Django form validation条件 Django 表单验证
【发布时间】:2021-02-01 15:27:50
【问题描述】:

对于一个 Django 项目,我有一个自定义的用户模型:

class User(AbstractUser):
    username = None
    email = models.EmailField(_('e-mail address'),
                              unique=True)
    first_name = models.CharField(_('first name'),
                                  max_length=150,
                                  blank=False)
    last_name = models.CharField(_('last name'),
                                  max_length=150,
                                  blank=False)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name']

    objects = UserManager()

    def __str__(self):
        return self.email

我正在创建一个新的用户注册表:

class UserRegistrationForm(forms.ModelForm):
    auto_password = forms.BooleanField(label=_('Generate password and send by mail'),
                                       required=False,
                                       initial=True)
    password = forms.CharField(label=_('Password'),
                               widget=forms.PasswordInput)
    password2 = forms.CharField(label=_('Repeat password'),
                                widget=forms.PasswordInput)

    class Meta:
        model = User
        fields = ('email', 'first_name', 'last_name', 'is_staff',
                  'is_superuser')

    def clean_password2(self):
        cd = self.cleaned_data
        if cd['password'] != cd['password2']:
            raise forms.ValidationError(_("Passwords don't match."))
        return cd['password2']

我的表单有一个 auto_password 布尔字段。设置此复选框时,不得选中 passwordpassword2 字段,因为它们的内容(或缺少内容)并不重要。相反,当auto_password复选框未设置时,passwordpassword2必须被选中。

有没有办法在需要时选择性地禁用 Django 表单检查?

感谢您的帮助。

【问题讨论】:

    标签: python django forms validation model


    【解决方案1】:

    您将其添加到clean 方法中的条件中:

    class UserRegistrationForm(forms.ModelForm):
        auto_password = forms.BooleanField(
            label=_('Generate password and send by mail'),
            required=False,
            initial=True
        )
        password = forms.CharField(
            label=_('Password'),
            widget=forms.PasswordInput
        )
        password2 = forms.CharField(
            label=_('Repeat password'),
            widget=forms.PasswordInput
        )
    
        class Meta:
            model = User
            fields = ('email', 'first_name', 'last_name', 'is_staff',
                      'is_superuser')
    
        def clean(self):
            data = super().clean()
            if not data['auto_password'] and data['password'] != data['password2']:
                raise forms.ValidationError(_('Passwords don't match.'))
            return data

    not data['auto_password'] 将因此返回False,以防选中复选框,在这种情况下,data['password'] != data['password2'] 的检查将不会运行,也不会引发ValidationError

    您还可以删除required=True 属性,并通过检查其真实性来检查password 是否包含至少一个字符:

    class UserRegistrationForm(forms.ModelForm):
        auto_password = forms.BooleanField(
            label=_('Generate password and send by mail'),
            # no required=True
            initial=True
        )
        password = forms.CharField(
            label=_('Password'),
            widget=forms.PasswordInput
        )
        password2 = forms.CharField(
            label=_('Repeat password'),
            widget=forms.PasswordInput
        )
    
        class Meta:
            model = User
            fields = ('email', 'first_name', 'last_name', 'is_staff',
                      'is_superuser')
    
        def clean(self):
            data = super().clean()
            manual = not data['auto_password']
            if manual and not data['password']:
                raise forms.ValidationError(_('Password is empty.'))
            if manual and data['password'] != data['password2']:
                raise forms.ValidationError(_('Passwords don't match.'))
            return data

    【讨论】:

    • 感谢您的回答和代码建议。不幸的是,Django 在 clean() 方法之前进行了另一次检查。当该字段为空时,它会显示“此字段为必填项”。密码和密码2。这是我想选择禁用的检查。
    • @amigne:然后将其包含在检查中,然后删除 required=True
    • 我正在寻找按需短路检查。但是您的建议(禁用检查并在需要时实施)肯定要好得多。非常感谢。
    【解决方案2】:

    你不能把它包含在你的逻辑中吗?

    if not cd['auto_password'] and (cd['password'] != cd['password2']):
        raise forms.ValidationError(_("Passwords don't match."))
    

    【讨论】:

    • 不幸的是,Django 在 clean() 方法之前进行了另一次检查。当该字段为空时,它会显示“此字段为必填项”。密码和密码2。这是我想选择禁用的检查。
    猜你喜欢
    • 2011-01-19
    • 2015-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-22
    • 2011-03-10
    • 2011-01-19
    相关资源
    最近更新 更多