diff options
| author | David Smith <smithdc@gmail.com> | 2021-09-10 08:06:01 +0100 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2021-09-20 15:50:18 +0200 |
| commit | 456466d932830b096d39806e291fe23ec5ed38d5 (patch) | |
| tree | 9320cc645ef43eb920630cff02c1387b34f21906 /docs | |
| parent | 5353e7c2505c0d0ab8232ad9c131b3c99c833988 (diff) | |
Fixed #31026 -- Switched form rendering to template engine.
Thanks Carlton Gibson, Keryn Knight, Mariusz Felisiak, and Nick Pope
for reviews.
Co-authored-by: Johannes Hoppe <info@johanneshoppe.com>
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/internals/deprecation.txt | 5 | ||||
| -rw-r--r-- | docs/ref/forms/api.txt | 204 | ||||
| -rw-r--r-- | docs/ref/forms/formsets.txt | 6 | ||||
| -rw-r--r-- | docs/ref/forms/models.txt | 18 | ||||
| -rw-r--r-- | docs/ref/forms/renderers.txt | 59 | ||||
| -rw-r--r-- | docs/ref/settings.txt | 5 | ||||
| -rw-r--r-- | docs/releases/4.0.txt | 17 | ||||
| -rw-r--r-- | docs/topics/forms/formsets.txt | 95 | ||||
| -rw-r--r-- | docs/topics/forms/index.txt | 24 |
9 files changed, 377 insertions, 56 deletions
diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index 23af7315dd..29af8cc7e2 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -57,6 +57,11 @@ details on these changes. * The ``django.contrib.gis.admin.GeoModelAdmin`` and ``OSMGeoAdmin`` classes will be removed. +* The undocumented ``BaseForm._html_output()`` method will be removed. + +* The ability to return a ``str``, rather than a ``SafeString``, when rendering + an ``ErrorDict`` and ``ErrorList`` will be removed. + .. _deprecation-removed-in-4.1: 4.1 diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt index 9cdbc21800..9dcfbcfb09 100644 --- a/docs/ref/forms/api.txt +++ b/docs/ref/forms/api.txt @@ -520,13 +520,41 @@ Although ``<table>`` output is the default output style when you ``print`` a form, other output styles are available. Each style is available as a method on a form object, and each rendering method returns a string. +``template_name`` +----------------- + +.. versionadded:: 4.0 + +.. attribute:: Form.template_name + +The name of a template that is going to be rendered if the form is cast into a +string, e.g. via ``print(form)`` or in a template via ``{{ form }}``. By +default this template is ``'django/forms/default.html'``, which is a proxy for +``'django/forms/table.html'``. The template can be changed per form by +overriding the ``template_name`` attribute or more generally by overriding the +default template, see also :ref:`overriding-built-in-form-templates`. + +``template_name_label`` +----------------------- + +.. versionadded:: 4.0 + +.. attribute:: Form.template_name_label + +The template used to render a field's ``<label>``, used when calling +:meth:`BoundField.label_tag`. Can be changed per form by overriding this +attribute or more generally by overriding the default template, see also +:ref:`overriding-built-in-form-templates`. + ``as_p()`` ---------- .. method:: Form.as_p() -``as_p()`` renders the form as a series of ``<p>`` tags, with each ``<p>`` -containing one field:: +``as_p()`` renders the form using the template assigned to the forms +``template_name_p`` attribute, by default this template is +``'django/forms/p.html'``. This template renders the form as a series of +``<p>`` tags, with each ``<p>`` containing one field:: >>> f = ContactForm() >>> f.as_p() @@ -542,10 +570,12 @@ containing one field:: .. method:: Form.as_ul() -``as_ul()`` renders the form as a series of ``<li>`` tags, with each -``<li>`` containing one field. It does *not* include the ``<ul>`` or -``</ul>``, so that you can specify any HTML attributes on the ``<ul>`` for -flexibility:: +``as_ul()`` renders the form using the template assigned to the forms +``template_name_ul`` attribute, by default this template is +``'django/forms/ul.html'``. This template renders the form as a series of +``<li>`` tags, with each ``<li>`` containing one field. It does *not* include +the ``<ul>`` or ``</ul>``, so that you can specify any HTML attributes on the +``<ul>`` for flexibility:: >>> f = ContactForm() >>> f.as_ul() @@ -561,9 +591,10 @@ flexibility:: .. method:: Form.as_table() -Finally, ``as_table()`` outputs the form as an HTML ``<table>``. This is -exactly the same as ``print``. In fact, when you ``print`` a form object, -it calls its ``as_table()`` method behind the scenes:: +Finally, ``as_table()`` renders the form using the template assigned to the +forms ``template_name_table`` attribute, by default this template is +``'django/forms/table.html'``. This template outputs the form as an HTML +``<table>``:: >>> f = ContactForm() >>> f.as_table() @@ -574,6 +605,37 @@ it calls its ``as_table()`` method behind the scenes:: <tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" required></td></tr> <tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself"></td></tr> +``get_context()`` +----------------- + +.. versionadded:: 4.0 + +.. method:: Form.get_context() + +Return context for form rendering in a template. + +The available context is: + +* ``form``: The bound form. +* ``fields``: All bound fields, except the hidden fields. +* ``hidden_fields``: All hidden bound fields. +* ``errors``: All non field related or hidden field related form errors. + +``render()`` +------------ + +.. versionadded:: 4.0 + +.. method:: Form.render(template_name=None, context=None, renderer=None) + +The render method is called by ``__str__`` as well as the +:meth:`.Form.as_table`, :meth:`.Form.as_p`, and :meth:`.Form.as_ul` methods. +All arguments are optional and default to: + +* ``template_name``: :attr:`.Form.template_name` +* ``context``: Value returned by :meth:`.Form.get_context` +* ``renderer``: Value returned by :attr:`.Form.default_renderer` + .. _ref-forms-api-styling-form-rows: Styling required or erroneous form rows @@ -834,25 +896,99 @@ method you're using:: Customizing the error list format --------------------------------- -By default, forms use ``django.forms.utils.ErrorList`` to format validation -errors. If you'd like to use an alternate class for displaying errors, you can -pass that in at construction time:: +.. class:: ErrorList(initlist=None, error_class=None, renderer=None) - >>> from django.forms.utils import ErrorList - >>> class DivErrorList(ErrorList): - ... def __str__(self): - ... return self.as_divs() - ... def as_divs(self): - ... if not self: return '' - ... return '<div class="errorlist">%s</div>' % ''.join(['<div class="error">%s</div>' % e for e in self]) - >>> f = ContactForm(data, auto_id=False, error_class=DivErrorList) - >>> f.as_p() - <div class="errorlist"><div class="error">This field is required.</div></div> - <p>Subject: <input type="text" name="subject" maxlength="100" required></p> - <p>Message: <input type="text" name="message" value="Hi there" required></p> - <div class="errorlist"><div class="error">Enter a valid email address.</div></div> - <p>Sender: <input type="email" name="sender" value="invalid email address" required></p> - <p>Cc myself: <input checked type="checkbox" name="cc_myself"></p> + 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. + + .. attribute:: error_class + + The CSS classes to be used when rendering the error list. Any provided + classes are added to the default ``errorlist`` class. + + .. attribute:: renderer + + .. versionadded:: 4.0 + + Specifies the :doc:`renderer <renderers>` to use for ``ErrorList``. + Defaults to ``None`` which means to use the default renderer + specified by the :setting:`FORM_RENDERER` setting. + + .. attribute:: template_name + + .. versionadded:: 4.0 + + The name of the template used when calling ``__str__`` or + :meth:`render`. By default this is + ``'django/forms/errors/list/default.html'`` which is a proxy for the + ``'ul.html'`` template. + + .. attribute:: template_name_text + + .. versionadded:: 4.0 + + The name of the template used when calling :meth:`.as_text`. By default + this is ``'django/forms/errors/list/text.html'``. This template renders + the errors as a list of bullet points. + + .. attribute:: template_name_ul + + .. versionadded:: 4.0 + + The name of the template used when calling :meth:`.as_ul`. By default + this is ``'django/forms/errors/list/ul.html'``. This template renders + the errors in ``<li>`` tags with a wrapping ``<ul>`` with the CSS + classes as defined by :attr:`.error_class`. + + .. method:: get_context() + + .. versionadded:: 4.0 + + Return context for rendering of errors in a template. + + The available context is: + + * ``errors`` : A list of the errors. + * ``error_class`` : A string of CSS classes. + + .. method:: render(template_name=None, context=None, renderer=None) + + .. versionadded:: 4.0 + + The render method is called by ``__str__`` as well as by the + :meth:`.as_ul` method. + + All arguments are optional and will default to: + + * ``template_name``: Value returned by :attr:`.template_name` + * ``context``: Value returned by :meth:`.get_context` + * ``renderer``: Value returned by :attr:`.renderer` + + .. method:: as_text() + + Renders the error list using the template defined by + :attr:`.template_name_text`. + + .. method:: as_ul() + + Renders the error list using the template defined by + :attr:`.template_name_ul`. + + If you'd like to customize the rendering of errors this can be achieved by + overriding the :attr:`.template_name` attribute or more generally by + overriding the default template, see also + :ref:`overriding-built-in-form-templates`. + +.. versionchanged:: 4.0 + + Rendering of :class:`ErrorList` was moved to the template engine. + +.. deprecated:: 4.0 + + The ability to return a ``str`` when calling the ``__str__`` method is + deprecated. Use the template engine instead which returns a ``SafeString``. More granular output ==================== @@ -1086,12 +1222,16 @@ Methods of ``BoundField`` attributes for the ``<label>`` tag. The HTML that's generated includes the form's - :attr:`~django.forms.Form.label_suffix` (a colon, by default) or, if set, the - current field's :attr:`~django.forms.Field.label_suffix`. The optional + :attr:`~django.forms.Form.label_suffix` (a colon, by default) or, if set, + the current field's :attr:`~django.forms.Field.label_suffix`. The optional ``label_suffix`` parameter allows you to override any previously set - suffix. For example, you can use an empty string to hide the label on selected - fields. If you need to do this in a template, you could write a custom - filter to allow passing parameters to ``label_tag``. + suffix. For example, you can use an empty string to hide the label on + selected fields. The label is rendered using the template specified by the + forms :attr:`.Form.template_name_label`. + + .. versionchanged:: 4.0 + + The label is now rendered using the template engine. .. method:: BoundField.value() diff --git a/docs/ref/forms/formsets.txt b/docs/ref/forms/formsets.txt index 0e281f2f59..677184df05 100644 --- a/docs/ref/forms/formsets.txt +++ b/docs/ref/forms/formsets.txt @@ -11,7 +11,7 @@ Formset API reference. For introductory material about formsets, see the ``formset_factory`` =================== -.. function:: formset_factory(form, formset=BaseFormSet, extra=1, can_order=False, can_delete=False, max_num=None, validate_max=False, min_num=None, validate_min=False, absolute_max=None, can_delete_extra=True) +.. function:: formset_factory(form, formset=BaseFormSet, extra=1, can_order=False, can_delete=False, max_num=None, validate_max=False, min_num=None, validate_min=False, absolute_max=None, can_delete_extra=True, renderer=None) Returns a ``FormSet`` class for the given ``form`` class. @@ -20,3 +20,7 @@ Formset API reference. For introductory material about formsets, see the .. versionchanged:: 3.2 The ``absolute_max`` and ``can_delete_extra`` arguments were added. + + .. versionchanged:: 4.0 + + The ``renderer`` argument was added. diff --git a/docs/ref/forms/models.txt b/docs/ref/forms/models.txt index 13ed69887e..59eac83e7d 100644 --- a/docs/ref/forms/models.txt +++ b/docs/ref/forms/models.txt @@ -52,7 +52,7 @@ Model Form API reference. For introductory material about model forms, see the ``modelformset_factory`` ======================== -.. function:: modelformset_factory(model, form=ModelForm, formfield_callback=None, formset=BaseModelFormSet, extra=1, can_delete=False, can_order=False, max_num=None, fields=None, exclude=None, widgets=None, validate_max=False, localized_fields=None, labels=None, help_texts=None, error_messages=None, min_num=None, validate_min=False, field_classes=None, absolute_max=None, can_delete_extra=True) +.. function:: modelformset_factory(model, form=ModelForm, formfield_callback=None, formset=BaseModelFormSet, extra=1, can_delete=False, can_order=False, max_num=None, fields=None, exclude=None, widgets=None, validate_max=False, localized_fields=None, labels=None, help_texts=None, error_messages=None, min_num=None, validate_min=False, field_classes=None, absolute_max=None, can_delete_extra=True, renderer=None) Returns a ``FormSet`` class for the given ``model`` class. @@ -63,9 +63,9 @@ Model Form API reference. For introductory material about model forms, see the Arguments ``formset``, ``extra``, ``can_delete``, ``can_order``, ``max_num``, ``validate_max``, ``min_num``, ``validate_min``, - ``absolute_max``, and ``can_delete_extra`` are passed through to - :func:`~django.forms.formsets.formset_factory`. See :doc:`formsets - </topics/forms/formsets>` for details. + ``absolute_max``, ``can_delete_extra``, and ``renderer`` are passed + through to :func:`~django.forms.formsets.formset_factory`. See + :doc:`formsets </topics/forms/formsets>` for details. See :ref:`model-formsets` for example usage. @@ -73,10 +73,14 @@ Model Form API reference. For introductory material about model forms, see the The ``absolute_max`` and ``can_delete_extra`` arguments were added. + .. versionchanged:: 4.0 + + The ``renderer`` argument was added. + ``inlineformset_factory`` ========================= -.. function:: inlineformset_factory(parent_model, model, form=ModelForm, formset=BaseInlineFormSet, fk_name=None, fields=None, exclude=None, extra=3, can_order=False, can_delete=True, max_num=None, formfield_callback=None, widgets=None, validate_max=False, localized_fields=None, labels=None, help_texts=None, error_messages=None, min_num=None, validate_min=False, field_classes=None, absolute_max=None, can_delete_extra=True) +.. function:: inlineformset_factory(parent_model, model, form=ModelForm, formset=BaseInlineFormSet, fk_name=None, fields=None, exclude=None, extra=3, can_order=False, can_delete=True, max_num=None, formfield_callback=None, widgets=None, validate_max=False, localized_fields=None, labels=None, help_texts=None, error_messages=None, min_num=None, validate_min=False, field_classes=None, absolute_max=None, can_delete_extra=True, renderer=None) Returns an ``InlineFormSet`` using :func:`modelformset_factory` with defaults of ``formset=``:class:`~django.forms.models.BaseInlineFormSet`, @@ -90,3 +94,7 @@ Model Form API reference. For introductory material about model forms, see the .. versionchanged:: 3.2 The ``absolute_max`` and ``can_delete_extra`` arguments were added. + + .. versionchanged:: 4.0 + + The ``renderer`` argument was added. diff --git a/docs/ref/forms/renderers.txt b/docs/ref/forms/renderers.txt index 58caa08c32..77ee33d662 100644 --- a/docs/ref/forms/renderers.txt +++ b/docs/ref/forms/renderers.txt @@ -68,11 +68,11 @@ it uses a :class:`~django.template.backends.jinja2.Jinja2` backend. Templates for the built-in widgets are located in ``django/forms/jinja2`` and installed apps can provide templates in a ``jinja2`` directory. -To use this backend, all the widgets in your project and its third-party apps -must have Jinja2 templates. Unless you provide your own Jinja2 templates for -widgets that don't have any, you can't use this renderer. For example, -:mod:`django.contrib.admin` doesn't include Jinja2 templates for its widgets -due to their usage of Django template tags. +To use this backend, all the forms and widgets in your project and its +third-party apps must have Jinja2 templates. Unless you provide your own Jinja2 +templates for widgets that don't have any, you can't use this renderer. For +example, :mod:`django.contrib.admin` doesn't include Jinja2 templates for its +widgets due to their usage of Django template tags. ``TemplatesSetting`` -------------------- @@ -97,6 +97,29 @@ Using this renderer along with the built-in widget templates requires either: Using this renderer requires you to make sure the form templates your project needs can be located. +Context available in formset templates +====================================== + +.. versionadded:: 4.0 + +Formset templates receive a context from :meth:`.BaseFormSet.get_context`. By +default, formsets receive a dictionary with the following values: + +* ``formset``: The formset instance. + +Context available in form templates +=================================== + +.. versionadded:: 4.0 + +Form templates receive a context from :meth:`.Form.get_context`. By default, +forms receive a dictionary with the following values: + +* ``form``: The bound form. +* ``fields``: All bound fields, except the hidden fields. +* ``hidden_fields``: All hidden bound fields. +* ``errors``: All non field related or hidden field related form errors. + Context available in widget templates ===================================== @@ -114,6 +137,32 @@ Some widgets add further information to the context. For instance, all widgets that subclass ``Input`` defines ``widget['type']`` and :class:`.MultiWidget` defines ``widget['subwidgets']`` for looping purposes. +.. _overriding-built-in-formset-templates: + +Overriding built-in formset templates +===================================== + +.. versionadded:: 4.0 + +:attr:`.BaseFormSet.template_name` + +To override formset templates, you must use the :class:`TemplatesSetting` +renderer. Then overriding widget templates works :doc:`the same as +</howto/overriding-templates>` overriding any other template in your project. + +.. _overriding-built-in-form-templates: + +Overriding built-in form templates +================================== + +.. versionadded:: 4.0 + +:attr:`.Form.template_name` + +To override form templates, you must use the :class:`TemplatesSetting` +renderer. Then overriding widget templates works :doc:`the same as +</howto/overriding-templates>` overriding any other template in your project. + .. _overriding-built-in-widget-templates: Overriding built-in widget templates diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index f534b8746c..a272bdbcb3 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -1671,8 +1671,9 @@ generate correct URLs when ``SCRIPT_NAME`` is not ``/``. Default: ``'``:class:`django.forms.renderers.DjangoTemplates`\ ``'`` -The class that renders form widgets. It must implement :ref:`the low-level -render API <low-level-widget-render-api>`. Included form renderers are: +The class that renders forms and form widgets. It must implement +:ref:`the low-level render API <low-level-widget-render-api>`. Included form +renderers are: * ``'``:class:`django.forms.renderers.DjangoTemplates`\ ``'`` * ``'``:class:`django.forms.renderers.Jinja2`\ ``'`` diff --git a/docs/releases/4.0.txt b/docs/releases/4.0.txt index de7ec8d93e..33abb0365e 100644 --- a/docs/releases/4.0.txt +++ b/docs/releases/4.0.txt @@ -115,6 +115,17 @@ in Django <redis>`. .. _`redis-py`: https://pypi.org/project/redis/ +Template based form rendering +----------------------------- + +To enhance customization of :class:`Forms <django.forms.Form>`, +:doc:`Formsets </topics/forms/formsets>`, and +:class:`~django.forms.ErrorList` they are now rendered using the template +engine. See the new :meth:`~django.forms.Form.render`, +:meth:`~django.forms.Form.get_context`, and +:attr:`~django.forms.Form.template_name` for ``Form`` and +:ref:`formset rendering <formset-rendering>` for ``Formset``. + Minor features -------------- @@ -735,6 +746,12 @@ Miscellaneous are deprecated. Use :class:`~django.contrib.admin.ModelAdmin` and :class:`~django.contrib.gis.admin.GISModelAdmin` instead. +* Since form rendering now uses the template engine, the undocumented + ``BaseForm._html_output()`` helper method is deprecated. + +* The ability to return a ``str`` from ``ErrorList`` and ``ErrorDict`` is + deprecated. It is expected these methods return a ``SafeString``. + Features removed in 4.0 ======================= diff --git a/docs/topics/forms/formsets.txt b/docs/topics/forms/formsets.txt index 30979edae4..e15f11dea0 100644 --- a/docs/topics/forms/formsets.txt +++ b/docs/topics/forms/formsets.txt @@ -775,9 +775,92 @@ But with ``ArticleFormset(prefix='article')`` that becomes: This is useful if you want to :ref:`use more than one formset in a view <multiple-formsets-in-view>`. +.. _formset-rendering: + Using a formset in views and templates ====================================== +Formsets have five attributes and five methods associated with rendering. + +.. attribute:: BaseFormSet.renderer + + .. versionadded:: 4.0 + + Specifies the :doc:`renderer </ref/forms/renderers>` to use for the + formset. Defaults to the renderer specified by the :setting:`FORM_RENDERER` + setting. + +.. attribute:: BaseFormSet.template_name + + .. versionadded:: 4.0 + + The name of the template used when calling ``__str__`` or :meth:`.render`. + This template renders the formsets management forms and then each form in + the formset as per the template defined by the + forms :attr:`~django.forms.Form.template_name`. This is a proxy of + ``as_table`` by default. + +.. attribute:: BaseFormSet.template_name_p + + .. versionadded:: 4.0 + + The name of the template used when calling :meth:`.as_p`. By default this + is ``'django/forms/formsets/p.html'``. This template renders the formsets + management forms and then each form in the formset as per the forms + :meth:`~django.forms.Form.as_p` method. + +.. attribute:: BaseFormSet.template_name_table + + .. versionadded:: 4.0 + + The name of the template used when calling :meth:`.as_table`. By default + this is ``'django/forms/formsets/table.html'``. This template renders the + formsets management forms and then each form in the formset as per the + forms :meth:`~django.forms.Form.as_table` method. + +.. attribute:: BaseFormSet.template_name_ul + + .. versionadded:: 4.0 + + The name of the template used when calling :meth:`.as_ul`. By default this + is ``'django/forms/formsets/ul.html'``. This template renders the formsets + management forms and then each form in the formset as per the forms + :meth:`~django.forms.Form.as_ul` method. + +.. method:: BaseFormSet.get_context() + + .. versionadded:: 4.0 + + Returns the context for rendering a formset in a template. + + The available context is: + + * ``formset`` : The instance of the formset. + +.. method:: BaseFormSet.render(template_name=None, context=None, renderer=None) + + .. versionadded:: 4.0 + + The render method is called by ``__str__`` as well as the :meth:`.as_p`, + :meth:`.as_ul`, and :meth:`.as_table` methods. All arguments are optional + and will default to: + + * ``template_name``: :attr:`.template_name` + * ``context``: Value returned by :meth:`.get_context` + * ``renderer``: Value returned by :attr:`.renderer` + +.. method:: BaseFormSet.as_p() + + Renders the formset with the :attr:`.template_name_p` template. + +.. method:: BaseFormSet.as_table() + + Renders the formset with the :attr:`.template_name_table` template. + +.. method:: BaseFormSet.as_ul() + + Renders the formset with the :attr:`.template_name_ul` template. + Using a formset inside a view is not very different from using a regular ``Form`` class. The only thing you will want to be aware of is making sure to use the management form inside the template. Let's look at a sample view:: @@ -821,7 +904,17 @@ deal with the management form: </table> </form> -The above ends up calling the ``as_table`` method on the formset class. +The above ends up calling the :meth:`BaseFormSet.render` method on the formset +class. This renders the formset using the template specified by the +:attr:`~BaseFormSet.template_name` attribute. Similar to forms, by default the +formset will be rendered ``as_table``, with other helper methods of ``as_p`` +and ``as_ul`` being available. The rendering of the formset can be customized +by specifying the ``template_name`` attribute, or more generally by +:ref:`overriding the default template <overriding-built-in-formset-templates>`. + +.. versionchanged:: 4.0 + + Rendering of formsets was moved to the template engine. .. _manually-rendered-can-delete-and-can-order: diff --git a/docs/topics/forms/index.txt b/docs/topics/forms/index.txt index eed18a2cee..8ed99d5773 100644 --- a/docs/topics/forms/index.txt +++ b/docs/topics/forms/index.txt @@ -733,12 +733,17 @@ Reusable form templates If your site uses the same rendering logic for forms in multiple places, you can reduce duplication by saving the form's loop in a standalone template and -using the :ttag:`include` tag to reuse it in other templates: +overriding the forms :attr:`~django.forms.Form.template_name` attribute to +render the form using the custom template. The below example will result in +``{{ form }}`` being rendered as the output of the ``form_snippet.html`` +template. + +In your templates: .. code-block:: html+django - # In your form template: - {% include "form_snippet.html" %} + # In your template: + {{ form }} # In form_snippet.html: {% for field in form %} @@ -748,16 +753,15 @@ using the :ttag:`include` tag to reuse it in other templates: </div> {% endfor %} -If the form object passed to a template has a different name within the -context, you can alias it using the ``with`` argument of the :ttag:`include` -tag: +In your form:: -.. code-block:: html+django + class MyForm(forms.Form): + template_name = 'form_snippet.html' + ... - {% include "form_snippet.html" with form=comment_form %} +.. versionchanged:: 4.0 -If you find yourself doing this often, you might consider creating a custom -:ref:`inclusion tag<howto-custom-template-tags-inclusion-tags>`. + Template rendering of forms was added. Further topics ============== |
