diff --git a/django/forms/forms.py b/django/forms/forms.py index 452f554e1e..549a3adf6f 100644 --- a/django/forms/forms.py +++ b/django/forms/forms.py @@ -298,7 +298,10 @@ class BaseForm(RenderableFormMixin): error_class="nonfield", renderer=self.renderer ) else: - self._errors[field] = self.error_class(renderer=self.renderer) + self._errors[field] = self.error_class( + renderer=self.renderer, + field_id=self[field].auto_id, + ) self._errors[field].extend(error_list) if field in self.cleaned_data: del self.cleaned_data[field] diff --git a/django/forms/jinja2/django/forms/errors/list/ul.html b/django/forms/jinja2/django/forms/errors/list/ul.html index 752f7c2c8b..59528efccc 100644 --- a/django/forms/jinja2/django/forms/errors/list/ul.html +++ b/django/forms/jinja2/django/forms/errors/list/ul.html @@ -1 +1 @@ -{% if errors %}{% endif %} +{% if errors %}{% endif %} diff --git a/django/forms/templates/django/forms/errors/list/ul.html b/django/forms/templates/django/forms/errors/list/ul.html index 57b34ccb88..c28ce8af67 100644 --- a/django/forms/templates/django/forms/errors/list/ul.html +++ b/django/forms/templates/django/forms/errors/list/ul.html @@ -1 +1 @@ -{% if errors %}{% endif %} \ No newline at end of file +{% if errors %}{% endif %} \ No newline at end of file diff --git a/django/forms/utils.py b/django/forms/utils.py index f4fbf3e241..d24711d1a0 100644 --- a/django/forms/utils.py +++ b/django/forms/utils.py @@ -147,7 +147,7 @@ class ErrorList(UserList, list, RenderableErrorMixin): template_name_text = "django/forms/errors/list/text.txt" template_name_ul = "django/forms/errors/list/ul.html" - def __init__(self, initlist=None, error_class=None, renderer=None): + def __init__(self, initlist=None, error_class=None, renderer=None, field_id=None): super().__init__(initlist) if error_class is None: @@ -155,6 +155,7 @@ class ErrorList(UserList, list, RenderableErrorMixin): else: self.error_class = "errorlist {}".format(error_class) self.renderer = renderer or get_default_renderer() + self.field_id = field_id def as_data(self): return ValidationError(self.data).error_list diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt index c6c83dcdfb..4875a1ab72 100644 --- a/docs/ref/forms/api.txt +++ b/docs/ref/forms/api.txt @@ -1025,13 +1025,17 @@ method you're using: Customizing the error list format --------------------------------- -.. class:: ErrorList(initlist=None, error_class=None, renderer=None) +.. class:: ErrorList(initlist=None, error_class=None, renderer=None, field_id=None) By default, forms use ``django.forms.utils.ErrorList`` to format validation errors. ``ErrorList`` is a list like object where ``initlist`` is the list of errors. In addition this class has the following attributes and methods. + .. versionchanged:: 5.2 + + The ``field_id`` argument was added. + .. attribute:: error_class The CSS classes to be used when rendering the error list. Any provided @@ -1043,6 +1047,16 @@ Customizing the error list format Defaults to ``None`` which means to use the default renderer specified by the :setting:`FORM_RENDERER` setting. + .. attribute:: field_id + + .. versionadded:: 5.2 + + An ``id`` for the field for which the errors relate. This allows an + HTML ``id`` attribute to be added in the error template and is useful + to associate the errors with the field. The default template uses the + format ``id="{{ field_id }}_error"`` and a value is provided by + :meth:`.Form.add_error` using the field's :attr:`~.BoundField.auto_id`. + .. attribute:: template_name The name of the template used when calling ``__str__`` or diff --git a/docs/releases/5.2.txt b/docs/releases/5.2.txt index 4b05fd3279..b6c44c43f8 100644 --- a/docs/releases/5.2.txt +++ b/docs/releases/5.2.txt @@ -249,6 +249,10 @@ Forms * The new :class:`~django.forms.TelInput` form widget is for entering telephone numbers and renders as ````. +* The new ``field_id`` argument for :class:`~django.forms.ErrorList` allows an + HTML ``id`` attribute to be added in the error template. See + :attr:`.ErrorList.field_id` for details. + Generic Views ~~~~~~~~~~~~~ diff --git a/tests/forms_tests/tests/test_error_messages.py b/tests/forms_tests/tests/test_error_messages.py index e44c6d6668..f4f5700107 100644 --- a/tests/forms_tests/tests/test_error_messages.py +++ b/tests/forms_tests/tests/test_error_messages.py @@ -249,7 +249,8 @@ class FormsErrorMessagesTestCase(SimpleTestCase, AssertFormErrorsMixin): form1 = TestForm({"first_name": "John"}) self.assertHTMLEqual( str(form1["last_name"].errors), - '', + '", ) self.assertHTMLEqual( str(form1.errors["__all__"]), @@ -280,7 +281,7 @@ class FormsErrorMessagesTestCase(SimpleTestCase, AssertFormErrorsMixin): f = SomeForm({"field": "