Django:覆盖表单中的 clean() 方法 - 关于引发错误的问题

Posted

技术标签:

【中文标题】Django:覆盖表单中的 clean() 方法 - 关于引发错误的问题【英文标题】:Django: Overriding the clean() method in forms - question about raising errors 【发布时间】:2011-01-08 04:35:53 【问题描述】:

我在 clean 方法中一直在做这样的事情:

if self.cleaned_data['type'].organized_by != self.cleaned_data['organized_by']:
      raise forms.ValidationError('The type and organization do not match.')
if self.cleaned_data['start'] > self.cleaned_data['end']:
      raise forms.ValidationError('The start date cannot be later than the end date.')

但这意味着表单一次只能引发其中一个错误。有没有办法让表单同时引发这两个错误?

编辑 #1: 上述任何解决方案都很棒,但希望在以下场景中也能工作的东西:

if self.cleaned_data['type'].organized_by != self.cleaned_data['organized_by']:
      raise forms.ValidationError('The type and organization do not match.')
if self.cleaned_data['start'] > self.cleaned_data['end']:
      raise forms.ValidationError('The start date cannot be later than the end date.')
super(FooAddForm, self).clean()

其中 FooAddForm 是一个 ModelForm 并且具有也可能导致错误的独特约束。如果有人知道这样的事情,那就太好了......

【问题讨论】:

【参考方案1】:
errors = []
if self.cleaned_data['type'].organized_by != self.cleaned_data['organized_by']:
      errors.append('The type and organization do not match.')
if self.cleaned_data['start'] > self.cleaned_data['end']:
     errors.append('The start date cannot be later than the end date.')

if errors:
    raise forms.ValidationError(errors)

【讨论】:

Grrr.... 试图给这个 +1,但我不小心点击了两次,现在它说“投票太旧了,无法更改”grrr...无论如何,很好的答案:) 但我'我仍然有一个问题......我在 ModelForm 上有一个干净的方法,检查唯一约束很重要,但如果我这样做:如果错误:引发 forms.ValidationError(errors) super(CompetitionAddForm, self).clean() 那么要么是我的错误,要么是唯一约束错误:-/【参考方案2】:

来自文档:

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

from django.forms.util import ErrorList

def clean(self):

  if self.cleaned_data['type'].organized_by != self.cleaned_data['organized_by']:
    msg = 'The type and organization do not match.'
    self._errors['type'] = ErrorList([msg])
    del self.cleaned_data['type']

  if self.cleaned_data['start'] > self.cleaned_data['end']:
    msg = 'The start date cannot be later than the end date.'
    self._errors['start'] = ErrorList([msg])
    del self.cleaned_data['start']

  return self.cleaned_data

【讨论】:

这很好用(我不确定我是否喜欢将错误消息附加到字段而不是整个表单,但实际上这样更有意义)和 ModelForm独特的约束也有效。所以我接受这个 - 谢谢! :)【参考方案3】:

如果您希望将错误消息附加到表单而不是特定字段,您可以使用键“__all__”,如下所示:

msg = 'The type and organization do not match.'
self._errors['__all__'] = ErrorList([msg])

此外,正如 Django 文档所解释的:“如果您想向特定字段添加新错误,您应该检查密钥是否已存在于 self._errors 中。如果不存在,请为给定的字段创建一个新条目键,持有一个空的ErrorList 实例。在任何一种情况下,您都可以将错误消息附加到相关字段名称的列表中,并在显示表单时显示。"

【讨论】:

【参考方案4】:

虽然它是旧帖子,但如果您想要更少的代码,您可以使用add_error() 方法添加错误消息。我正在扩展@kemar 的答案以显示用例:

add_error() 自动从cleaned_data 字典中删除该字段,您不必手动删除它。 你也不必导入任何东西来使用它。

documentation is here

def clean(self):

  if self.cleaned_data['type'].organized_by != self.cleaned_data['organized_by']:
    msg = 'The type and organization do not match.'
    self.add_error('type', msg)

  if self.cleaned_data['start'] > self.cleaned_data['end']:
    msg = 'The start date cannot be later than the end date.'
    self.add_error('start', msg)

  return self.cleaned_data

【讨论】:

以上是关于Django:覆盖表单中的 clean() 方法 - 关于引发错误的问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 clean 更改 Django formset 中的字段

is_valid() vs clean() django 表单

Django:如何使表单有条件?

Django 表单验证、clean() 和文件上传

即使缺少所需的值,Django 验证也会调用 clean()

Django - 表单 Clean() 和字段错误