【问题标题】:django - how to process/clean a field before validationdjango - 如何在验证之前处理/清理字段
【发布时间】: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>()?还是我应该以其他方式这样做?

【问题讨论】:

    标签: django validation django-forms


    【解决方案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 是否为空

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-01-17
          • 1970-01-01
          • 2020-06-22
          • 2016-06-04
          • 1970-01-01
          • 1970-01-01
          • 2012-10-11
          • 1970-01-01
          相关资源
          最近更新 更多