diff --git a/django/forms/boundfield.py b/django/forms/boundfield.py index 6764276148..39b0aaf97b 100644 --- a/django/forms/boundfield.py +++ b/django/forms/boundfield.py @@ -1,7 +1,7 @@ import re from django.core.exceptions import ValidationError -from django.forms.utils import pretty_name +from django.forms.utils import RenderableFieldMixin, pretty_name from django.forms.widgets import MultiWidget, Textarea, TextInput from django.utils.functional import cached_property from django.utils.html import format_html, html_safe @@ -10,8 +10,7 @@ from django.utils.translation import gettext_lazy as _ __all__ = ("BoundField",) -@html_safe -class BoundField: +class BoundField(RenderableFieldMixin): "A Field plus data" def __init__(self, form, field, name): @@ -26,12 +25,7 @@ class BoundField: else: self.label = self.field.label self.help_text = field.help_text or "" - - def __str__(self): - """Render this field as an HTML widget.""" - if self.field.show_hidden_initial: - return self.as_widget() + self.as_hidden(only_initial=True) - return self.as_widget() + self.renderer = form.renderer @cached_property def subwidgets(self): @@ -81,6 +75,13 @@ class BoundField: self.name, self.form.error_class(renderer=self.form.renderer) ) + @property + def template_name(self): + return self.field.template_name or self.form.renderer.field_template_name + + def get_context(self): + return {"field": self} + def as_widget(self, widget=None, attrs=None, only_initial=False): """ Render the field by rendering the passed widget, adding any HTML diff --git a/django/forms/fields.py b/django/forms/fields.py index 003fb5ca6b..0143296533 100644 --- a/django/forms/fields.py +++ b/django/forms/fields.py @@ -107,6 +107,7 @@ class Field: localize=False, disabled=False, label_suffix=None, + template_name=None, ): # required -- Boolean that specifies whether the field is required. # True by default. @@ -164,6 +165,7 @@ class Field: self.error_messages = messages self.validators = [*self.default_validators, *validators] + self.template_name = template_name super().__init__() diff --git a/django/forms/jinja2/django/forms/div.html b/django/forms/jinja2/django/forms/div.html index 6de0bb038e..f297874e4a 100644 --- a/django/forms/jinja2/django/forms/div.html +++ b/django/forms/jinja2/django/forms/div.html @@ -4,16 +4,7 @@ {% endif %} {% for field, errors in fields %}
elements.""" diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt index 12754dbae5..4d4f73d0b4 100644 --- a/docs/ref/forms/api.txt +++ b/docs/ref/forms/api.txt @@ -1257,6 +1257,16 @@ Attributes of ``BoundField`` >>> print(f["message"].name) message +.. attribute:: BoundField.template_name + + .. versionadded:: 5.0 + + The name of the template rendered with :meth:`.BoundField.as_field_group`. + + A property returning the value of the + :attr:`~django.forms.Field.template_name` if set otherwise + :attr:`~django.forms.renderers.BaseRenderer.field_template_name`. + .. attribute:: BoundField.use_fieldset Returns the value of this BoundField widget's ``use_fieldset`` attribute. @@ -1281,6 +1291,15 @@ Attributes of ``BoundField`` Methods of ``BoundField`` ------------------------- +.. method:: BoundField.as_field_group() + + .. versionadded:: 5.0 + + Renders the field using :meth:`.BoundField.render` with default values + which renders the ``BoundField``, including its label, help text and errors + using the template's :attr:`~django.forms.Field.template_name` if set + otherwise :attr:`~django.forms.renderers.BaseRenderer.field_template_name` + .. method:: BoundField.as_hidden(attrs=None, **kwargs) Returns a string of HTML for representing this as an ````. @@ -1321,6 +1340,13 @@ Methods of ``BoundField`` >>> f["message"].css_classes("foo bar") 'foo bar required' +.. method:: BoundField.get_context() + + .. versionadded:: 5.0 + + Return the template context for rendering the field. The available context + is ``field`` being the instance of the bound field. + .. method:: BoundField.label_tag(contents=None, attrs=None, label_suffix=None, tag=None) Renders a label tag for the form field using the template specified by @@ -1368,6 +1394,20 @@ Methods of ``BoundField`` checkbox widgets where ``