Подтвердить что ты не робот

Ошибка визуализации формы с меткой, а не именем поля

Я хотел бы перечислить все ошибки формы вместе с помощью {{form.errors}} в шаблоне. Это создает список полей формы и вложенных списков ошибок для каждого поля. Однако используется буквальное имя поля. Сгенерированный html с ошибкой в ​​определенном поле может выглядеть так.

<ul class="errorlist">
    <li>
        target_date_mdcy
        <ul class="errorlist">
            <li>This field is required.</li>
        </ul>
    </li>
</ul>

Я хотел бы использовать функцию списка ошибок, так как это приятно и легко. Тем не менее, я хочу использовать метку ( "Целевая дата", скажем), а не имя поля. На самом деле, я не могу придумать случай, в котором вы хотите, чтобы имя поля отображалось для пользователя веб-страницы. Можно ли использовать отображаемый список ошибок с меткой поля?

4b9b3361

Ответ 1

Я не вижу простого способа сделать это.

Атрибут ошибок формы фактически возвращает ErrorDict, класс, определенный в django.forms.utils - это подкласс dict, который знает, чтобы произвести это отображение в себе как его представление в Юникоде. Но ключи на самом деле являются именами полей, и это важно для поддержания другого поведения. Таким образом, он не обеспечивает легкий доступ к меткам поля.

Вы можете определить собственный тег шаблона, который принимает форму для получения рендеринга, который вы предпочитаете, поскольку в коде 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 в списке, в зависимости.

Ответ 2

Я знаю, что это уже ответили, но я столкнулся с одним и тем же сценарием и обнаружил, что существует простой способ использования метки:

{% 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 %}

Ответ 3

Я решил это в классе пользовательской формы, который наследует все мои формы вместо 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 ...

Ответ 4

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 в представлениях.

Ответ 5

На всякий случай, если кто-то ищет что-то подобное, используя фреймворк 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] не имеет смысла.

Ответ 6

Здесь фильтр, который я использовал для отображения списка ошибок с меткой поля, следуя предложению Питера.

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