diff options
| author | Carlton Gibson <carlton.gibson@noumenal.es> | 2022-05-03 16:07:01 +0200 |
|---|---|---|
| committer | Carlton Gibson <carlton@noumenal.es> | 2022-05-04 11:52:48 +0200 |
| commit | fde946daffbb007a7d033945677cc8e9e475d516 (patch) | |
| tree | bdb7a439b5c10da70c502e38cb48b93fc82654d1 /docs | |
| parent | 5d91dc8ee3ff7e2230cfacf41005f61b8efbf057 (diff) | |
Refs #32339 -- Restructured outputting HTML form docs.
In the topic doc, promoted the Reusable form templates section.
In the reference, re-grouped and promoted the default __str__()
rendering path, and then gathered the various as_*() helpers
subsequently.
Thanks to David Smith for review.
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/ref/forms/api.txt | 128 | ||||
| -rw-r--r-- | docs/topics/forms/index.txt | 139 |
2 files changed, 149 insertions, 118 deletions
diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt index a6b4d11f4a..8530af2611 100644 --- a/docs/ref/forms/api.txt +++ b/docs/ref/forms/api.txt @@ -520,9 +520,15 @@ 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`` +Default rendering ----------------- +The default rendering when you ``print`` a form uses the following methods and +attributes. + +``template_name`` +~~~~~~~~~~~~~~~~~ + .. versionadded:: 4.0 .. attribute:: Form.template_name @@ -540,8 +546,42 @@ class. In older versions ``template_name`` defaulted to the string value ``'django/forms/default.html'``. +``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` + +By passing ``template_name`` you can customize the template used for just a +single call. + +``get_context()`` +~~~~~~~~~~~~~~~~~ + +.. versionadded:: 4.0 + +.. method:: Form.get_context() + +Return the template context for rendering the form. + +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. + ``template_name_label`` ------------------------ +~~~~~~~~~~~~~~~~~~~~~~~ .. versionadded:: 4.0 @@ -552,15 +592,32 @@ The template used to render a field's ``<label>``, used when calling form by overriding this attribute or more generally by overriding the default template, see also :ref:`overriding-built-in-form-templates`. +Output styles +------------- + +As well as rendering the form directly, such as in a template with +``{{ form }}``, the following helper functions serve as a proxy to +:meth:`Form.render` passing a particular ``template_name`` value. + +These helpers are most useful in a template, where you need to override the +form renderer or form provided value but cannot pass the additional parameter +to :meth:`~Form.render`. For example, you can render a form as an unordered +list using ``{{ form.as_ul }}``. + +Each helper pairs a form method with an attribute giving the appropriate +template name. + ``as_p()`` ----------- +~~~~~~~~~~ + +.. attribute:: Form.template_name_p + +The template used by ``as_p()``. Default: ``'django/forms/p.html'``. .. method:: Form.as_p() -``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:: +``as_p()`` renders the form as a series of ``<p>`` tags, with each ``<p>`` +containing one field:: >>> f = ContactForm() >>> f.as_p() @@ -572,16 +629,17 @@ template, see also :ref:`overriding-built-in-form-templates`. <p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"></p> ``as_ul()`` ------------ +~~~~~~~~~~~ + +.. attribute:: Form.template_name_ul + +The template used by ``as_ul()``. Default: ``'django/forms/ul.html'``. .. method:: Form.as_ul() -``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:: +``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:: >>> f = ContactForm() >>> f.as_ul() @@ -593,14 +651,15 @@ the ``<ul>`` or ``</ul>``, so that you can specify any HTML attributes on the <li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"></li> ``as_table()`` --------------- +~~~~~~~~~~~~~~ + +.. attribute:: Form.template_name_table + +The template used by ``as_table()``. Default: ``'django/forms/table.html'``. .. method:: Form.as_table() -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>``:: +``as_table()`` renders the form as an HTML ``<table>``:: >>> f = ContactForm() >>> f.as_table() @@ -611,37 +670,6 @@ forms ``template_name_table`` attribute, by default this template is <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 diff --git a/docs/topics/forms/index.txt b/docs/topics/forms/index.txt index e7709834c2..c8e43389a0 100644 --- a/docs/topics/forms/index.txt +++ b/docs/topics/forms/index.txt @@ -487,15 +487,83 @@ instance into the template context. So if your form is called ``form`` in the context, ``{{ form }}`` will render its ``<label>`` and ``<input>`` elements appropriately. -Form rendering options ----------------------- - .. admonition:: Additional form template furniture Don't forget that a form's output does *not* include the surrounding ``<form>`` tags, or the form's ``submit`` control. You will have to provide these yourself. +Reusable form templates +----------------------- + +The HTML output when rendering a form is itself generated via a template. You +can control this by creating an appropriate template file and setting a custom +:setting:`FORM_RENDERER` to use that +:attr:`~django.forms.renderers.BaseRenderer.form_template_name` site-wide. You +can also customize per-form by overriding the form's +:attr:`~django.forms.Form.template_name` attribute to render the form using the +custom template, or by passing the template name directly to +:meth:`.Form.render`. + +The example below will result in ``{{ form }}`` being rendered as the output of +the ``form_snippet.html`` template. + +In your templates: + +.. code-block:: html+django + + # In your template: + {{ form }} + + # In form_snippet.html: + {% for field in form %} + <div class="fieldWrapper"> + {{ field.errors }} + {{ field.label_tag }} {{ field }} + </div> + {% endfor %} + +Then you can configure the :setting:`FORM_RENDERER` setting: + +.. code-block:: python + :caption: settings.py + + from django.forms.renderers import TemplatesSetting + + class CustomFormRenderer(TemplatesSetting): + form_template_name = "form_snippet.html" + + FORM_RENDERER = "project.settings.CustomFormRenderer" + +… or for a single form:: + + class MyForm(forms.Form): + template_name = "form_snippet.html" + ... + +… or for a single render of a form instance, passing in the template name to +the :meth:`.Form.render`. Here's an example of this being used in a view:: + + def index(request): + form = MyForm() + rendered_form = form.render("form_snippet.html") + context = {'form': rendered_form} + return render(request, 'index.html', context) + +See :ref:`ref-forms-api-outputting-html` for more details. + +.. versionchanged:: 4.0 + + Template rendering of forms was added. + +.. versionchanged:: 4.1 + + The ability to set the default ``form_template_name`` on the form renderer + was added. + +Form rendering options +---------------------- + There are other output options though for the ``<label>``/``<input>`` pairs: * ``{{ form.as_table }}`` will render them as table cells wrapped in ``<tr>`` @@ -754,71 +822,6 @@ error in a hidden field is a sign of form tampering, since normal form interaction won't alter them. However, you could easily insert some error displays for those form errors, as well. -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 -setting a custom :setting:`FORM_RENDERER` to use that -:attr:`~django.forms.renderers.BaseRenderer.form_template_name` site-wide. You -can also customize per-form by overriding the form's -: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 template: - {{ form }} - - # In form_snippet.html: - {% for field in form %} - <div class="fieldWrapper"> - {{ field.errors }} - {{ field.label_tag }} {{ field }} - </div> - {% endfor %} - -Then you can configure the :setting:`FORM_RENDERER` setting: - -.. code-block:: python - :caption: settings.py - - from django.forms.renderers import TemplatesSetting - - class CustomFormRenderer(TemplatesSetting): - form_template_name = "form_snippet.html" - - FORM_RENDERER = "project.settings.CustomFormRenderer" - -… or for a single form:: - - class MyForm(forms.Form): - template_name = "form_snippet.html" - ... - -… or for a single render of a form instance, passing in the template name to -the :meth:`.Form.render()`. Here's an example of this being used in a view:: - - def index(request): - form = MyForm() - rendered_form = form.render("form_snippet.html") - context = {'form': rendered_form} - return render(request, 'index.html', context) - -.. versionchanged:: 4.0 - - Template rendering of forms was added. - -.. versionchanged:: 4.1 - - The ability to set the default ``form_template_name`` on the form renderer - was added. - Further topics ============== |
