在 Django 中重置复选框

Reset checkbox in Django

我决定重写问题:

我有以下表格:

class TOUMixin(forms.Form):
    error_messages = {
        'accept_tou': _("You must read and accept tou"),
    }
    accept_tou = forms.BooleanField(label=_('I have read and accept tou'), initial=False, required=False)
def clean_accept_tou(self):
    value = self.cleaned_data.get('accept_tou')
    if not value:
        raise forms.ValidationError(
            self.error_messages['accept_tou'],
            code='accept_tou',
        )
    return value

class SetPasswordMixin(forms.Form):
    error_messages = {
        'password_mismatch': _("The two password fields didn't match."),
    }
    password1 = PasswordStrengthField(label=_("Password"), widget=forms.PasswordInput)
    password2 = forms.CharField(label=_("Password (again)"), widget=forms.PasswordInput,
                                help_text=_("Enter the same password as above, for verification."))

    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(
                    self.error_messages['password_mismatch'],
                    code='password_mismatch',
                )
        return password2


class TOUSetPasswordMixin(TOUMixin, SetPasswordMixin):
    error_messages = dict(SetPasswordMixin.error_messages, **TOUMixin.error_messages)

class UserForm(forms.ModelForm, TOUSetPasswordMixin):
    captcha = ReCaptchaField()

    class Meta:
        model = User
        fields = ('email', 'password1', 'password2')

    def __init__(self, model, *args, **kwargs):
        self.model = model
        super(UserForm, self).__init__(*args, **kwargs)

    def save(self, commit=True):
        user = self.model.create(email=self.instance.email)
        user.set_password(self.cleaned_data['password1'])
        if commit:
            user.save()
        return user

UserForm无效时,我需要重置accept_tou。最好在 TOUMixin 中完成,因为该字段用于其他形式。

我喜欢 form_valid 的回答,所以在 TOUMixin 里面我写了以下内容:

def is_valid(self):
  result = super(TOUMixin, self).is_valid()
  if not result:
     self.cleaned_data['accept_tou'] = False
  return result

但是,这不起作用。 clean 方法未被调用,因为据我所知,它被 ModelForm 的 clean 方法覆盖(抱歉,@catavaran)。

我将它移到了 UserForm,它被调用了,但没有工作。复选框已选中。

您可以定义可以验证和更改数据的 clean_FIELD_NAME() 方法,如此处所述:

https://docs.djangoproject.com/en/dev/ref/forms/validation/#cleaning-a-specific-field-attribute

或者使用这个:

https://docs.djangoproject.com/en/dev/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other

您的问题中没有任何示例代码。我不能给你举个例子。

您应该覆盖 UserForm.clean() 方法:

class UserForm(forms.ModelForm, TOUSetPasswordMixin):    

    def clean(self):
        super(UserForm, self).clean()
        if self.errors:
            self.data = self.data.copy()
            self.data['accept_tou'] = ''

我做到了!

感谢大家,尤其是@catavaran。

我刚刚更改了错误词典中的值。 这行得通。

class TOUMixin(forms.Form):
    error_messages = {
        'accept_tou': _("You must read and accept tou"),
    }
    accept_tou = forms.BooleanField(label=_('I have read and accept tou'), initial=False, required=False)

    def clean_accept_tou(self):
        value = self.cleaned_data.get('accept_tou')
        if not value:
            raise forms.ValidationError(
                self.error_messages['accept_tou'],
                code='accept_tou',
            )
        return value

    def is_valid(self):
        result = super(TOUMixin, self).is_valid()
        if not result:
            self.data.pop('accept_tou', None)
        return result