django - 如何在验证之前处理/清理字段

时间:2011-02-06 15:16:36

标签: django validation django-forms

我有一个表格,只有在清理后才需要验证。

运行form.is_valid()时会发生什么?是否清理了表单,然后验证了表单的已清理版本?

我目前正在采取的行为是,如果我的字段在清理之前没有通过验证,即使清理会通过验证,is_valid()也会返回False

我做错了吗?

代码:

# View
class ContactForm(forms.Form):
    message = forms.CharField(widget=forms.Textarea, max_length=5)

    def clean_message(self):
        message = self.cleaned_data['message']
        return message.replace('a', '') # remove all "a"s from message

def contact(request):
    if request.method == 'POST':
        if form.is_valid():
            return HttpResponseRedirect('/contact/on_success/')
        else:
            return HttpResponseRedirect('/contact/on_failure/')

如果邮件少于5个字符包括form.is_valid(),我希望True返回a

是否可以在clean_<fieldname>()之后to_python()之前运行run_validators()?或者我应该以其他方式这样做吗?

4 个答案:

答案 0 :(得分:33)

我认为表单验证的过程(及其正确的顺序)确实有很好的记录。 http://docs.djangoproject.com/en/dev/ref/forms/validation/#form-and-field-validation

你介意分享你的代码吗?每个表单域都有clean方法,负责运行to_pythonvalidaterun_validators(按此顺序)。 to_python接受窗口小部件的原始值,将其强制转换为python类型,validate获取强制值并运行特定于字段的验证。

根据给定的代码更新了答案

clean_messageto_python以及最重要的validate之类的所有其他验证运行后,

run_validators被调用。我认为最后一种方法将检查是否违反了max_length约束。所以你之后更改数据没有任何影响。

解决方案是在这里举起ValidationError。删除max_length将避免对输入的长度进行任何验证。

class ContactForm(forms.Form):
    message = forms.CharField(widget=forms.Textarea)

    def clean_message(self):
        message = self.cleaned_data['message']
        message = message.replace('a', '') # remove all "a"s from message
        if len(message) >= 5:
            raise ValidationError('Too many characters ...')
        return message

答案 1 :(得分:2)

另外,当is_valid()返回False时,您可以检查原因,在表单中打印self.errors

如果您查看is_valid()代码,则会检查表单is_bound并且self.errors为空

答案 2 :(得分:0)

您可以覆盖CharField:

class CustomCharField(forms.CharField):
    def clean(self, value):
        return super().clean(value.replace('a', ''))

然后您可以使用表格

class ContactForm(forms.Form):
    message = CustomCharField(widget=forms.Textarea)

答案 3 :(得分:-1)

只需添加到Reiner Gerecke。

当在窗体上调用is_valid()方法时,MultiEmailField.clean()方法将作为清理过程的一部分运行,它将依次调用自定义的to_python()和validate()方法。 enter image description here