Вы можете поставить уникальный идентификатор в каждом сообщении об ошибке, но это немного сложно, и я не уверен, насколько "безопасным" я бы это считал. Я думаю, что лучшей альтернативой для того, что вы хотите, является перебор полей в форме и рендеринг поля и сообщений об ошибках по одному. В конце этого поста описывается, как это сделать. Если вам действительно нужно поместить идентификаторы в сообщения об ошибках без циклического перебора полей в шаблоне ... хорошо, продолжайте читать.
Трудный путь
Чтобы получить больше, чем простое текстовое сообщение, отображаемое для каждого сообщения об ошибке (без разбивки формы в шаблоне), вам нужно предоставить класс ErrorList
, альтернативный ModelForm
. Класс ErrorList
- это то, что выполняет рендеринг ошибок в HTML, поэтому, создав и используя подкласс, вы можете изменить то, что рендерится, включая добавление специального кода из самой ошибки ValidationError.
from django.forms.utils import ErrorList
from django.utils.html import format_html, format_html_join
# This overrides the ErrorList class to provide the additional rendering
# features you want - in this example it only overrides it for the `ul` output
class ErrorListDerivative(ErrorList):
def as_ul(self):
if not self.data:
return ''
# Key part 1: the UL is now being rendered with a class for
# each of the errors which includes the error code from the
# ValidationError. You can then locate the UL by looking for that class.
return format_html(
'<ul class="{{}} {}">{{}}</ul>'.format(' '.join(('errorcode{}'.format(e.code) for e in self.data))),
self.error_class,
# Key Part 2: This adds the code from the validation error to the individual LIs
format_html_join('', '<li class="errorforcode{}">{}</li>', ((e.code, e.message) for e in self.data))
)
Теперь, создав ErrorList, который отображает вещи так, как вы хотите, он должен использоваться TestForm.
class TestForm(forms.ModelForm):
# This __init__ is what makes the ModelForm use the custom ErrorList class you've created.
# The BaseForm from which ModelForm is derived (a few layers of inheritence deep) has an `error_class` argument to receive the class used to render errors. This just injects your custom class.
def __init__(self, *args, **kwargs):
kwargs_new = {'error_class': ErrorListDerivative}
kwargs_new.update(kwargs)
super().__init__(*args, **kwargs_new)
class Meta:
model = Restaurant
fields = [
'title',
'content',
]
Затем, внутри вашей функции очистки TestForm, вы передаете дополнительный code
в ValidationErrors
def clean(self, *args, **kwargs):
title = self.cleaned_data.get("title")
content = self.cleaned_data.get("content")
error_dict = {}
# Key Part 3: Here we're including the custom error code in the
# ValidationError, which will be rendered out
if len(title) < 3:
error_dict['title'] = ValidationError("testerror1", code='title')
if len(content) < 3:
error_dict['content'] = ValidationError('testerror2', code='content')
if error_dict:
# Must admit, not sure if adding a code here will do anything at all
raise ValidationError(error_dict, code='3')
После того, как вы это сделаете, вывод HTML должен выглядеть примерно так:
<form id="my_form_id" method="post" novalidate="">
<label for="id_title">Title:</label>
<ul class="errorlist errorcodetitle">
<li class="errorforcodetitle">testerror1</li>
</ul><input type="text" name="title" value="ao" maxlength="100" required="" id="id_title">
<label for="id_content">Content:</label>
<ul class="errorlist errorcodecontent">
<li class="errorforcodecontent">testerror2</li>
</ul><input type="text" name="content" value="ao" maxlength="100" required="" id="id_content">
<button type="submit">Submit</button>
</form>
Теперь, когда класс на этих UL, вы можете использовать имя поле, чтобы найти соответствующий UL и скрыть его.
$("#my_form_id").find('input, textarea').click(function(evt) {
$('.errorcode' + this.name).hide();
})
Идиомати c Путь
Если вы не хотите go вниз по этой кроличьей норе, альтернативой является сделать что-то более похожее на пример в django документах для «зацикливания полей формы» (https://docs.djangoproject.com/en/3.0/topics/forms/#looping -over-the-form-s-fields ) Это не дает вам пользовательские классы (или идентификаторы, что вы в конечном итоге добавить) на й Сообщения об ошибках, но они гораздо более идиоматичны c.
Что-то вроде следующего ...
{% for field in form %}
<div class="fieldWrapper">
<div class="errorcode{{field.html_name}}">
{{ field.errors }}
</div>
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
Тогда вы можете использовать тот же jquery, как было описано выше:
$("#my_form_id").find('input, textarea').click(function(evt) {
$('.errorcode' + this.name).hide();
})