Django表单触发ValidationError立即终止:验证码错误不执行clean_address方法
问题原因
Django表单默认会按字段定义顺序执行所有字段的校验逻辑(包括clean_<fieldname>自定义校验),就算前面的字段校验失败也不会中途终止,所以验证码校验失败后依然会执行clean_address里的逻辑。
解决方法
重写表单的全局clean方法,把address的自定义校验逻辑放到全局校验的最后,前置字段有错误时直接终止后续逻辑:
from django import forms from captcha.fields import ReCaptchaField from .models import Server, Category from .utils.status_manager import ServerStatus class AddServerForm(forms.ModelForm): captcha = ReCaptchaField() categories = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple(attrs={'class': 'checkbox'}), error_messages={ 'required': 'You need to select server type' }, choices=[(c.pk, c.name) for c in Category.objects.all()] ) def clean(self): cleaned_data = super().clean() # 前置字段校验失败直接终止后续逻辑 if self.errors: return cleaned_data # 原clean_address的校验逻辑移到此处 address = cleaned_data.get('address') if address: if Server.objects.filter(address=address).exists(): self.add_error('address', "Server is on the list") return cleaned_data if not ServerStatus(address).is_server_on(): self.add_error('address', "Server is offline") return cleaned_data return cleaned_data class Meta: model = Server fields = ['address']
说明
- 全局
clean方法执行前,已经完成所有前置字段的基础校验(包括recaptcha校验、categories必填校验),只要self.errors中存在错误就直接返回,不会触发address的自定义校验 - 用
add_error方法绑定字段错误,和原clean_address抛出错误的前端展示效果完全一致,不会影响原有错误提示逻辑
内容的提问来源于stack exchange,提问作者ivall
相关产品推荐
相关产品推荐

