====================== The form rendering API ====================== .. module:: django.forms.renderers :synopsis: Built-in form renderers. Django's form widgets are rendered using Django's :doc:`template engines system `. The form rendering process can be customized at several levels: * Widgets can specify custom template names. * Forms and widgets can specify custom renderer classes. * A widget's template can be overridden by a project. (Reusable applications typically shouldn't override built-in templates because they might conflict with a project's custom templates.) .. _low-level-widget-render-api: The low-level render API ======================== The rendering of form templates is controlled by a customizable renderer class. A custom renderer can be specified by updating the :setting:`FORM_RENDERER` setting. It defaults to ``'``:class:`django.forms.renderers.DjangoTemplates`\ ``'``. By specifying a custom form renderer and overriding :attr:`~.BaseRenderer.form_template_name` you can adjust the default form markup across your project from a single place. You can also provide a custom renderer per-form or per-widget by setting the :attr:`.Form.default_renderer` attribute or by using the ``renderer`` argument of :meth:`.Form.render`, or :meth:`.Widget.render`. Matching points apply to formset rendering. See :ref:`formset-rendering` for discussion. Use one of the :ref:`built-in template form renderers ` or implement your own. Custom renderers must implement a ``render(template_name, context, request=None)`` method. It should return a rendered templates (as a string) or raise :exc:`~django.template.TemplateDoesNotExist`. .. class:: BaseRenderer The base class for the built-in form renderers. .. attribute:: form_template_name .. versionadded:: 4.1 The default name of the template to use to render a form. Defaults to ``"django/forms/default.html"``, which is a proxy for ``"django/forms/table.html"``. .. deprecated:: 4.1 The ``"django/forms/default.html"`` template is deprecated and will be removed in Django 5.0. The default will become ``"django/forms/div.html"`` at that time. .. attribute:: formset_template_name .. versionadded:: 4.1 The default name of the template to use to render a formset. Defaults to ``"django/forms/formsets/default.html"``, which is a proxy for ``"django/forms/formsets/table.html"``. .. deprecated:: 4.1 The ``"django/forms/formset/default.html"`` template is deprecated and will be removed in Django 5.0. The default will become ``"django/forms/formset/div.html"`` template. .. method:: get_template(template_name) Subclasses must implement this method with the appropriate template finding logic. .. method:: render(template_name, context, request=None) Renders the given template, or raises :exc:`~django.template.TemplateDoesNotExist`. .. _built-in-template-form-renderers: Built-in-template form renderers ================================ ``DjangoTemplates`` ------------------- .. class:: DjangoTemplates This renderer uses a standalone :class:`~django.template.backends.django.DjangoTemplates` engine (unconnected to what you might have configured in the :setting:`TEMPLATES` setting). It loads templates first from the built-in form templates directory in :source:`django/forms/templates` and then from the installed apps' templates directories using the :class:`app_directories ` loader. If you want to render templates with customizations from your :setting:`TEMPLATES` setting, such as context processors for example, use the :class:`TemplatesSetting` renderer. .. class:: DjangoDivFormRenderer .. versionadded:: 4.1 Subclass of :class:`DjangoTemplates` that specifies :attr:`~BaseRenderer.form_template_name` and :attr:`~BaseRenderer.formset_template_name` as ``"django/forms/div.html"`` and ``"django/forms/formset/div.html"`` respectively. This is a transitional renderer for opt-in to the new ``
`` based templates, which are the default from Django 5.0. Apply this via the :setting:`FORM_RENDERER` setting:: FORM_RENDERER = "django.forms.renderers.DjangoDivFormRenderer" Once the ``
`` templates are the default, this transitional renderer will be deprecated, for removal in Django 6.0. The ``FORM_RENDERER`` declaration can be removed at that time. ``Jinja2`` ---------- .. class:: Jinja2 This renderer is the same as the :class:`DjangoTemplates` renderer except that it uses a :class:`~django.template.backends.jinja2.Jinja2` backend. Templates for the built-in widgets are located in :source:`django/forms/jinja2` and installed apps can provide templates in a ``jinja2`` directory. 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. .. class:: Jinja2DivFormRenderer .. versionadded:: 4.1 A transitional renderer as per :class:`DjangoDivFormRenderer` above, but subclassing :class:`Jinja2` for use with the Jinja2 backend. Apply this via the :setting:`FORM_RENDERER` setting:: FORM_RENDERER = "django.forms.renderers.Jinja2DivFormRenderer" ``TemplatesSetting`` -------------------- .. class:: TemplatesSetting This renderer gives you complete control of how form and widget templates are sourced. It uses :func:`~django.template.loader.get_template` to find templates based on what's configured in the :setting:`TEMPLATES` setting. Using this renderer along with the built-in templates requires either: * ``'django.forms'`` in :setting:`INSTALLED_APPS` and at least one engine with :setting:`APP_DIRS=True `. * Adding the built-in templates directory in :setting:`DIRS ` of one of your template engines. To generate that path:: import django django.__path__[0] + '/forms/templates' # or '/forms/jinja2' Using this renderer requires you to make sure the form templates your project needs can be located. Context available in formset templates ====================================== 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 =================================== 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 ===================================== Widget templates receive a context from :meth:`.Widget.get_context`. By default, widgets receive a single value in the context, ``widget``. This is a dictionary that contains values like: * ``name`` * ``value`` * ``attrs`` * ``is_hidden`` * ``template_name`` 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 ===================================== :attr:`.BaseFormSet.template_name` To override formset templates, you must use the :class:`TemplatesSetting` renderer. Then overriding widget templates works :doc:`the same as ` overriding any other template in your project. .. _overriding-built-in-form-templates: Overriding built-in form templates ================================== :attr:`.Form.template_name` To override form templates, you must use the :class:`TemplatesSetting` renderer. Then overriding widget templates works :doc:`the same as ` overriding any other template in your project. .. _overriding-built-in-widget-templates: Overriding built-in widget templates ==================================== Each widget has a ``template_name`` attribute with a value such as ``input.html``. Built-in widget templates are stored in the ``django/forms/widgets`` path. You can provide a custom template for ``input.html`` by defining ``django/forms/widgets/input.html``, for example. See :ref:`built-in widgets` for the name of each widget's template. To override widget templates, you must use the :class:`TemplatesSetting` renderer. Then overriding widget templates works :doc:`the same as ` overriding any other template in your project.