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

Posted

技术标签:

【中文标题】django - 如何在验证之前处理/清理字段【英文标题】:django - how to process/clean a field before validation 【发布时间】:2011-06-22 07:07:15 【问题描述】:

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

当你运行 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 个字符,包括a,我希望form.is_valid() 返回True

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

【问题讨论】:

【参考方案1】:

我认为表单验证的过程(及其正确顺序)真的是well documented。

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

根据给出的代码更新答案

clean_message 在所有其他验证运行后调用,如to_pythonvalidate,最重要的是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

【讨论】:

我添加了一些简化的代码来展示我想要实现的目标。感谢您的帮助。 引发新错误如何阻止当前错误被引发? Edit: 哦,对了,那我可以从现场删除max_length!对吗? @Acorn 是的,你可以删除它。我认为是必需的,但这适用于模型。 所以它的要点。我需要在我的clean_<fieldname>() 中进行验证,而不是使用max_length【参考方案2】:

您可以覆盖 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】:

只是添加到 Reiner Gerecke。

当在表单上调用 is_valid() 方法时,MultiEmailField.clean() 方法将作为清理过程的一部分运行,然后它会调用自定义的 to_python() 和 validate() 方法。 Just read the "Form field default cleaning" part and its example

【讨论】:

【参考方案4】:

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

如果您查看is_valid() 代码,则会检查is_bound 的形式,而self.errors 是否为空

【讨论】:

以上是关于django - 如何在验证之前处理/清理字段的主要内容,如果未能解决你的问题,请参考以下文章

django一次清理多个字段

在 Django 中清理表单数据

如何使用魔法来验证 Django 表单清理方法中的文件类型?

在 django 中将 css 类添加到验证错误的字段

django - 如何清理 url 传递的变量数据?

Django - 如何指定验证失败的字段?