The form rendering API¶
Django’s form widgets are rendered using Django’s 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.)
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 FORM_RENDERER
setting. It defaults to
'
django.forms.renderers.DjangoTemplates
'
.
By specifying a custom form renderer and overriding
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
Form.default_renderer
attribute or by using the renderer
argument
of Form.render()
, or Widget.render()
.
Matching points apply to formset rendering. See Using a formset in views and templates for discussion.
Use one of the 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
TemplateDoesNotExist
.
-
class
BaseRenderer
[source]¶ The base class for the built-in form renderers.
-
form_template_name
¶ - New in Django 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 since version 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.
-
formset_template_name
¶ - New in Django 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 since version 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.
-
get_template
(template_name)[source]¶ Subclasses must implement this method with the appropriate template finding logic.
-
render
(template_name, context, request=None)[source]¶ Renders the given template, or raises
TemplateDoesNotExist
.
-
Built-in-template form renderers¶
DjangoTemplates
¶
This renderer uses a standalone
DjangoTemplates
engine (unconnected to what you might have configured in the
TEMPLATES
setting). It loads templates first from the built-in form
templates directory in django/forms/templates and then from the
installed apps’ templates directories using the app_directories
loader.
If you want to render templates with customizations from your
TEMPLATES
setting, such as context processors for example, use the
TemplatesSetting
renderer.
Subclass of DjangoTemplates
that specifies
form_template_name
and
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 <div>
based
templates, which are the default from Django 5.0.
Apply this via the FORM_RENDERER
setting:
FORM_RENDERER = "django.forms.renderers.DjangoDivFormRenderer"
Once the <div>
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
¶
This renderer is the same as the DjangoTemplates
renderer except that
it uses a 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 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, django.contrib.admin
doesn’t include Jinja2 templates for its
widgets due to their usage of Django template tags.
A transitional renderer as per DjangoDivFormRenderer
above, but
subclassing Jinja2
for use with the Jinja2 backend.
Apply this via the FORM_RENDERER
setting:
FORM_RENDERER = "django.forms.renderers.Jinja2DivFormRenderer"
TemplatesSetting
¶
This renderer gives you complete control of how form and widget templates are
sourced. It uses get_template()
to find templates
based on what’s configured in the TEMPLATES
setting.
Using this renderer along with the built-in templates requires either:
'django.forms'
inINSTALLED_APPS
and at least one engine withAPP_DIRS=True
.Adding the built-in templates directory in
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 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 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 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 MultiWidget
defines widget['subwidgets']
for looping purposes.
Overriding built-in formset templates¶
To override formset templates, you must use the TemplatesSetting
renderer. Then overriding formset templates works the same as overriding any other template in your project.
Overriding built-in form templates¶
To override form templates, you must use the TemplatesSetting
renderer. Then overriding form templates works the same as overriding any other template in your project.
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 Built-in widgets for the name of each widget’s template.
To override widget templates, you must use the TemplatesSetting
renderer. Then overriding widget templates works the same as overriding any other template in your project.