Django’s form widgets are rendered using Django’s template engines system.
The form rendering process can be customized at several levels:
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
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.
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.
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
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, django.contrib.admin doesn’t include Jinja2 templates for its widgets due to their usage of Django template tags.
Using this renderer along with the built-in widget templates requires either:
Adding the built-in widgets templates directory in DIRS of one of your template engines. To generate that path:
import django django.__path__ + '/forms/templates' # or '/forms/jinja2'
Using this renderer requires you to make sure the form templates your project needs can be located.
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:
Some widgets add further information to the context. For instance, all widgets that subclass
widget['type'] and MultiWidget defines
widget['subwidgets'] for looping purposes.
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.