我想在模板中使用{{form.errors}}列出所有表单错误。这将生成一个表单字段列表和每个字段的错误的嵌套列表。但是,使用该字段的文字名称。在特定字段中生成的带有错误的html可能如下所示。
<ul class="errorlist">
<li>
target_date_mdcy
<ul class="errorlist">
<li>This field is required.</li>
</ul>
</li>
</ul>
我想使用错误列表功能,因为它很简单。但是,我想使用标签(比如说“目标日期”)而不是字段名称。实际上,我想不出你希望为网页用户显示字段名称的情况。有没有办法使用带有字段标签的渲染错误列表?
答案 0 :(得分:9)
我没有看到一种简单的方法来做到这一点。
表单的errors属性实际上返回一个ErrorDict
,一个在django.forms.utils
中定义的类 - 它是dict
的子类,它知道将其自身的ul渲染作为其unicode表示。但键实际上是字段名称,这对于维护其他行为很重要。因此,它无法轻松访问字段标签。
您可以定义一个自定义模板标记,它接受表单以生成您喜欢的呈现,因为在Python代码中,很容易获得给定表单和字段名称的字段标签。或者,您可以在视图中按标签构造错误列表,将其添加到您的上下文中,然后使用它。
修改的
或者,您可以迭代字段并检查其各自的错误,并记住也显示non_field_errors
。类似的东西:
<ul class="errorlist">
{% if form.non_field_errors %}
<li>{{ form.non_field_errors }}</li>
{% endif %}
{% for field in form %}
{% if field.errors %}
<li>
{{ field.label }}
<ul class="errorlist">
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>
您可能希望将non_field_errors包装在列表中,具体取决于。
答案 1 :(得分:9)
我知道这已经得到了解答,但我遇到了同样的情况,发现有一种简单的方法可以使用标签:
{% if form.errors %}
<ul class="user-msg error">
{% for field in form %}
{% for error in field.errors %}
<li>
{% if field != '__all__' %}
<strong>{{ field.label }}:</strong>
{% endif %}
{{ error }}
</li>
{% endfor %}
{% endfor %}
</ul>
{% endif %}
答案 2 :(得分:2)
我在自定义表单类中解决了这个问题,我的所有表单都继承而不是django.forms.Form
。在那里,我通过返回form.errors
方法考虑标签的自定义ErrorDict
来更改as_ul
的工作方式。因此,您无需更改模板,但需要让表单继承CustomBaseForm
。
class CustomErrorDict(ErrorDict):
def __init__(self, form, iterable=None, **kwargs):
self.form = form
super(CustomErrorDict, self).__init__(iterable, **kwargs)
def as_ul(self):
if not self:
return u''
def humanify(field_name):
try:
return self.form.fields[field_name].label or field_name
except:
return field_name
# main logic is copied from the original ErrorDict:
return mark_safe(u'<ul class="errorlist">%s</ul>'
% ''.join([u'<li>%s%s</li>' % (humanify(k), force_unicode(v))
for k, v in self.items()]))
class CustomBaseForm(forms.Form):
@property
def errors(self):
return CustomErrorDict(self, super(forms.Form, self).errors)
... rest of CustomBaseForm ...
答案 3 :(得分:2)
from django import forms
def my_clean(self):
self.my_errors = ''
for x in self.visible_fields():
if x.errors:
self.my_errors += "<p>%s: %s</p>" % (x.label, x.errors)
class SetPwdForm(forms.Form):
pwd= forms.CharField(label='password', required=True, min_length=6)
def clean(self):
...
my_clean(self)
在视图中使用 myform.my_errors 。
答案 4 :(得分:0)
以防万一有人使用django.contrib.messages
框架进行此类操作,例如FormView
:
def form_invalid(self, form):
for field, errors in form.errors.items():
for error in errors:
messages.error(
self.request,
form.fields[field].label + ": " + error
)
请注意,这只是一个基本模板,在form.fields[field]
没有意义的情况下,您必须处理代码中的非字段错误等。
答案 5 :(得分:0)
以下方法显示 verbose_name
而不是字段名称。
它也可以在 get_context_data()
中使用,但就我个人而言,我更喜欢这种方式:
from django.core.exceptions import FieldDoesNotExist
class ShowVerboseNameInFormsMixin:
def add_error(self, field, error):
super(ShowVerboseNameInFormsMixin, self).add_error(field, error)
for field, message in self._errors.copy().items():
try:
verbose_name = self._meta.model._meta.get_field(field).verbose_name
del self._errors[field]
self._errors[verbose_name] = self.error_class()
self._errors[verbose_name].extend(message)
except FieldDoesNotExist:
pass
然后像这样使用它:
from django import forms
class FooForm(ShowVerboseNameInFormsMixin, forms.ModelForm):
class Meta:
model = Foo
fields = ['foo', 'bar', 'baz']
用一点额外的代码,它可以显示 __all__
到 all
或任何其他预期的字符串。
答案 6 :(得分:-1)
这是我用来根据彼得的建议用字段标签呈现错误列表的过滤器。
from django.utils.safestring import mark_safe
from django.template import Library, Context, loader
register = Library()
@register.filter
def form_error_list(form):
result = ""
if form.errors:
fields = form.fields
error_items = []
for error_field in form.errors:
label = fields[error_field].label
if not label:
label = ' '.join([word.capitalize() for word in error_field.split('_')])
errors = form.errors[error_field]
error_li = ''.join(['<li>{0}</li>'.format(error) for error in errors])
error_items.append({'label': label, 'error_li': error_li})
inner = ''.join(['<li>{0}<ul class="errorlist">{1}</ul></li>'.format(item['label'], item['error_li']) for item in error_items])
result = mark_safe('<ul class="errorlist">{0}</ul>'.format(inner))
return result