Python 使用标签而不是字段名呈现表单错误

Python 使用标签而不是字段名呈现表单错误,python,django,django-forms,Python,Django,Django Forms,我想使用模板中的{{form.errors}}将所有表单错误一起列出。这将生成表单字段列表和每个字段的错误嵌套列表。但是,将使用字段的文字名称。生成的html在特定字段中出现错误,可能如下所示 <ul class="errorlist"> <li> target_date_mdcy <ul class="errorlist"> <li>This field is required.&l

我想使用模板中的{{form.errors}}将所有表单错误一起列出。这将生成表单字段列表和每个字段的错误嵌套列表。但是,将使用字段的文字名称。生成的html在特定字段中出现错误,可能如下所示

<ul class="errorlist">
    <li>
        target_date_mdcy
        <ul class="errorlist">
            <li>This field is required.</li>
        </ul>
    </li>
</ul>
  • 目标日期
    • 此字段为必填字段

我想使用错误列表功能,因为它很好,很简单。但是,我想使用标签(“Target Date”,比如)而不是字段名。事实上,我想不出有哪种情况下,您希望为网页用户显示字段名。有没有办法将渲染的错误列表与字段标签一起使用?

我看不到一种简单的方法

表单的errors属性实际上返回一个
ErrorDict
,一个在
django.forms.utils
中定义的类,它是
dict
的一个子类,知道如何将自身作为unicode表示生成ul呈现。但键实际上是字段名,这对于其他行为很重要。因此,它无法轻松访问字段标签

您可以定义一个接受表单的自定义模板标记来生成您喜欢的呈现,因为在Python代码中,给定表单和字段名很容易获得字段标签。或者,您可以在视图中按标签构造错误列表,将其添加到上下文中,然后使用它

编辑 或者,您也可以遍历字段并检查它们各自的错误,同时记住显示
非字段错误
。比如:

<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>
    {%if form.non_字段_错误%}
  • {{form.non_field_errors}}
  • {%endif%} {%形式的字段为%} {%if field.errors%}
  • {{field.label}
      {%字段中有错误。错误%}
    • {{error}}
    • {%endfor%}
  • {%endif%} {%endfor%}

您可能还希望将非字段错误包装到列表中,具体取决于。

以下是我根据Peter的建议,用于呈现带有字段标签的错误列表的过滤器

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
来自django.utils.safestring导入标记\u safe
从django.template导入库、上下文、加载程序
寄存器=库()
@寄存器过滤器
def表单错误列表(表单):
result=“”
如果form.errors:
fields=form.fields
错误项=[]
对于form.errors中的error_字段:
label=字段[错误\字段]。label
如果没有标签:
label=''.join([word.capitalize()表示错误字段中的单词.split(''))
错误=表单。错误[错误\u字段]
错误_li=''.join(['
  • {0}
  • '.format(error)表示错误中的错误]) 错误\u项。追加({'label':label'error\u li':error\u li}) inner=''.join(['
  • {0}
      {1}
  • ')。格式(错误项中的项['label',项['error\u li'])) 结果=标记安全('
      {0}
    '.format(内部)) 返回结果
    我知道这一点已经得到了回答,但我遇到了相同的情况,发现有一种简单的方法可以使用标签:

    {% 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 %}
    
    {%if form.errors%}
    
      {%形式的字段为%} {%字段中有错误。错误%}
    • {%if字段!='\uuuuu all\uuuuuu%} {field.label}: {%endif%} {{error}}
    • {%endfor%} {%endfor%}
    {%endif%}
    我在一个自定义表单类中解决了这个问题,我的所有表单都继承该类,而不是
    django.forms.form
    。在那里,我改变了
    表单的工作方式。通过返回一个自定义
    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 ...
    
    class CustomErrorDict(ErrorDict):
    定义初始化(self,form,iterable=None,**kwargs):
    self.form=form
    超级(CustomErrorDict,self)。\uuuu初始化(iterable,**kwargs)
    def as_ul(自身):
    如果不是自己:
    返回u“
    def humanify(字段名称):
    尝试:
    返回self.form.fields[字段名称].标签或字段名称
    除:
    返回字段名称
    #主逻辑从原始ErrorDict复制:
    返回安全标记(u'
      %s
    ' %''.join([u'
  • %s%s
  • '%(humanify(k),force_unicode(v)) 对于self.items()]中的k,v) 类CustomBaseForm(forms.Form): @财产 def错误(自我): 返回CustomErrorDict(self,super(forms.Form,self.errors) ... CustomBaseForm的其余部分。。。
    来自django导入表单
    定义my_清洁(自我):
    self.my_errors=''
    对于self.visible_字段()中的x:
    如果x.0错误:
    self.my_errors+=“%s:%s

    ”%(x.label,x.errors) 类SetPwdForm(forms.Form): pwd=forms.CharField(label='password',required=True,最小长度=6) def清洁(自清洁): ... 我的清洁(自我)

    在视图中使用myform.my\u错误。

    以防有人在查看时使用
    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]
    没有意义,您必须注意代码中的非字段错误等。

    谢谢,Peter。我不知道关于ErrorDict的事。我使用了自定义过滤器,因为我可能会继续使用它。如果您有任何非字段错误,这将引发异常-对于完整的一般情况,您将
    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
                )