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 表单