mirror of
https://github.com/django/django.git
synced 2024-11-28 10:48:32 +01:00
1000 lines
36 KiB
Plaintext
1000 lines
36 KiB
Plaintext
=======
|
|
Widgets
|
|
=======
|
|
|
|
.. module:: django.forms.widgets
|
|
:synopsis: Django's built-in form widgets.
|
|
|
|
.. currentmodule:: django.forms
|
|
|
|
A widget is Django's representation of an HTML input element. The widget
|
|
handles the rendering of the HTML, and the extraction of data from a GET/POST
|
|
dictionary that corresponds to the widget.
|
|
|
|
The HTML generated by the built-in widgets uses HTML5 syntax, targeting
|
|
``<!DOCTYPE html>``. For example, it uses boolean attributes such as ``checked``
|
|
rather than the XHTML style of ``checked='checked'``.
|
|
|
|
.. tip::
|
|
|
|
Widgets should not be confused with the :doc:`form fields </ref/forms/fields>`.
|
|
Form fields deal with the logic of input validation and are used directly
|
|
in templates. Widgets deal with rendering of HTML form input elements on
|
|
the web page and extraction of raw submitted data. However, widgets do
|
|
need to be :ref:`assigned <widget-to-field>` to form fields.
|
|
|
|
.. _widget-to-field:
|
|
|
|
Specifying widgets
|
|
==================
|
|
|
|
Whenever you specify a field on a form, Django will use a default widget
|
|
that is appropriate to the type of data that is to be displayed. To find
|
|
which widget is used on which field, see the documentation about
|
|
:ref:`built-in-fields`.
|
|
|
|
However, if you want to use a different widget for a field, you can
|
|
use the :attr:`~Field.widget` argument on the field definition. For example::
|
|
|
|
from django import forms
|
|
|
|
|
|
class CommentForm(forms.Form):
|
|
name = forms.CharField()
|
|
url = forms.URLField()
|
|
comment = forms.CharField(widget=forms.Textarea)
|
|
|
|
This would specify a form with a comment that uses a larger :class:`Textarea`
|
|
widget, rather than the default :class:`TextInput` widget.
|
|
|
|
Setting arguments for widgets
|
|
=============================
|
|
|
|
Many widgets have optional extra arguments; they can be set when defining the
|
|
widget on the field. In the following example, the
|
|
:attr:`~django.forms.SelectDateWidget.years` attribute is set for a
|
|
:class:`~django.forms.SelectDateWidget`::
|
|
|
|
from django import forms
|
|
|
|
BIRTH_YEAR_CHOICES = ["1980", "1981", "1982"]
|
|
FAVORITE_COLORS_CHOICES = {
|
|
"blue": "Blue",
|
|
"green": "Green",
|
|
"black": "Black",
|
|
}
|
|
|
|
|
|
class SimpleForm(forms.Form):
|
|
birth_year = forms.DateField(
|
|
widget=forms.SelectDateWidget(years=BIRTH_YEAR_CHOICES)
|
|
)
|
|
favorite_colors = forms.MultipleChoiceField(
|
|
required=False,
|
|
widget=forms.CheckboxSelectMultiple,
|
|
choices=FAVORITE_COLORS_CHOICES,
|
|
)
|
|
|
|
See the :ref:`built-in widgets` for more information about which widgets
|
|
are available and which arguments they accept.
|
|
|
|
Widgets inheriting from the ``Select`` widget
|
|
=============================================
|
|
|
|
Widgets inheriting from the :class:`Select` widget deal with choices. They
|
|
present the user with a list of options to choose from. The different widgets
|
|
present this choice differently; the :class:`Select` widget itself uses a
|
|
``<select>`` HTML list representation, while :class:`RadioSelect` uses radio
|
|
buttons.
|
|
|
|
:class:`Select` widgets are used by default on :class:`ChoiceField` fields. The
|
|
choices displayed on the widget are inherited from the :class:`ChoiceField` and
|
|
changing :attr:`ChoiceField.choices` will update :attr:`Select.choices`. For
|
|
example:
|
|
|
|
.. code-block:: pycon
|
|
|
|
>>> from django import forms
|
|
>>> CHOICES = {"1": "First", "2": "Second"}
|
|
>>> choice_field = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES)
|
|
>>> choice_field.choices
|
|
[('1', 'First'), ('2', 'Second')]
|
|
>>> choice_field.widget.choices
|
|
[('1', 'First'), ('2', 'Second')]
|
|
>>> choice_field.widget.choices = []
|
|
>>> choice_field.choices = [("1", "First and only")]
|
|
>>> choice_field.widget.choices
|
|
[('1', 'First and only')]
|
|
|
|
Widgets which offer a :attr:`~Select.choices` attribute can however be used
|
|
with fields which are not based on choice -- such as a :class:`CharField` --
|
|
but it is recommended to use a :class:`ChoiceField`-based field when the
|
|
choices are inherent to the model and not just the representational widget.
|
|
|
|
Customizing widget instances
|
|
============================
|
|
|
|
When Django renders a widget as HTML, it only renders very minimal markup -
|
|
Django doesn't add class names, or any other widget-specific attributes. This
|
|
means, for example, that all :class:`TextInput` widgets will appear the same
|
|
on your web pages.
|
|
|
|
There are two ways to customize widgets: :ref:`per widget instance
|
|
<styling-widget-instances>` and :ref:`per widget class <styling-widget-classes>`.
|
|
|
|
.. _styling-widget-instances:
|
|
|
|
Styling widget instances
|
|
------------------------
|
|
|
|
If you want to make one widget instance look different from another, you will
|
|
need to specify additional attributes at the time when the widget object is
|
|
instantiated and assigned to a form field (and perhaps add some rules to your
|
|
CSS files).
|
|
|
|
For example, take the following form::
|
|
|
|
from django import forms
|
|
|
|
|
|
class CommentForm(forms.Form):
|
|
name = forms.CharField()
|
|
url = forms.URLField()
|
|
comment = forms.CharField()
|
|
|
|
This form will include three default :class:`TextInput` widgets, with default
|
|
rendering -- no CSS class, no extra attributes. This means that the input boxes
|
|
provided for each widget will be rendered exactly the same:
|
|
|
|
.. code-block:: pycon
|
|
|
|
>>> f = CommentForm(auto_id=False)
|
|
>>> print(f)
|
|
<div>Name:<input type="text" name="name" required></div>
|
|
<div>Url:<input type="url" name="url" required></div>
|
|
<div>Comment:<input type="text" name="comment" required></div>
|
|
|
|
On a real web page, you probably don't want every widget to look the same. You
|
|
might want a larger input element for the comment, and you might want the
|
|
'name' widget to have some special CSS class. It is also possible to specify
|
|
the 'type' attribute to take advantage of the new HTML5 input types. To do
|
|
this, you use the :attr:`Widget.attrs` argument when creating the widget::
|
|
|
|
class CommentForm(forms.Form):
|
|
name = forms.CharField(widget=forms.TextInput(attrs={"class": "special"}))
|
|
url = forms.URLField()
|
|
comment = forms.CharField(widget=forms.TextInput(attrs={"size": "40"}))
|
|
|
|
You can also modify a widget in the form definition::
|
|
|
|
class CommentForm(forms.Form):
|
|
name = forms.CharField()
|
|
url = forms.URLField()
|
|
comment = forms.CharField()
|
|
|
|
name.widget.attrs.update({"class": "special"})
|
|
comment.widget.attrs.update(size="40")
|
|
|
|
Or if the field isn't declared directly on the form (such as model form fields),
|
|
you can use the :attr:`Form.fields` attribute::
|
|
|
|
class CommentForm(forms.ModelForm):
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.fields["name"].widget.attrs.update({"class": "special"})
|
|
self.fields["comment"].widget.attrs.update(size="40")
|
|
|
|
Django will then include the extra attributes in the rendered output:
|
|
|
|
>>> f = CommentForm(auto_id=False)
|
|
>>> print(f)
|
|
<div>Name:<input type="text" name="name" class="special" required></div>
|
|
<div>Url:<input type="url" name="url" required></div>
|
|
<div>Comment:<input type="text" name="comment" size="40" required></div>
|
|
|
|
You can also set the HTML ``id`` using :attr:`~Widget.attrs`. See
|
|
:attr:`BoundField.id_for_label` for an example.
|
|
|
|
.. _styling-widget-classes:
|
|
|
|
Styling widget classes
|
|
----------------------
|
|
|
|
With widgets, it is possible to add assets (``css`` and ``javascript``)
|
|
and more deeply customize their appearance and behavior.
|
|
|
|
In a nutshell, you will need to subclass the widget and either
|
|
:ref:`define a "Media" inner class <assets-as-a-static-definition>` or
|
|
:ref:`create a "media" property <dynamic-property>`.
|
|
|
|
These methods involve somewhat advanced Python programming and are described in
|
|
detail in the :doc:`Form Assets </topics/forms/media>` topic guide.
|
|
|
|
.. _base-widget-classes:
|
|
|
|
Base widget classes
|
|
===================
|
|
|
|
Base widget classes :class:`Widget` and :class:`MultiWidget` are subclassed by
|
|
all the :ref:`built-in widgets <built-in widgets>` and may serve as a
|
|
foundation for custom widgets.
|
|
|
|
``Widget``
|
|
----------
|
|
|
|
.. class:: Widget(attrs=None)
|
|
|
|
This abstract class cannot be rendered, but provides the basic attribute
|
|
:attr:`~Widget.attrs`. You may also implement or override the
|
|
:meth:`~Widget.render()` method on custom widgets.
|
|
|
|
.. attribute:: Widget.attrs
|
|
|
|
A dictionary containing HTML attributes to be set on the rendered
|
|
widget.
|
|
|
|
.. code-block:: pycon
|
|
|
|
>>> from django import forms
|
|
>>> name = forms.TextInput(attrs={"size": 10, "title": "Your name"})
|
|
>>> name.render("name", "A name")
|
|
'<input title="Your name" type="text" name="name" value="A name" size="10">'
|
|
|
|
If you assign a value of ``True`` or ``False`` to an attribute,
|
|
it will be rendered as an HTML5 boolean attribute:
|
|
|
|
.. code-block:: pycon
|
|
|
|
>>> name = forms.TextInput(attrs={"required": True})
|
|
>>> name.render("name", "A name")
|
|
'<input name="name" type="text" value="A name" required>'
|
|
>>>
|
|
>>> name = forms.TextInput(attrs={"required": False})
|
|
>>> name.render("name", "A name")
|
|
'<input name="name" type="text" value="A name">'
|
|
|
|
.. attribute:: Widget.supports_microseconds
|
|
|
|
An attribute that defaults to ``True``. If set to ``False``, the
|
|
microseconds part of :class:`~datetime.datetime` and
|
|
:class:`~datetime.time` values will be set to ``0``.
|
|
|
|
.. method:: format_value(value)
|
|
|
|
Cleans and returns a value for use in the widget template. ``value``
|
|
isn't guaranteed to be valid input, therefore subclass implementations
|
|
should program defensively.
|
|
|
|
.. method:: get_context(name, value, attrs)
|
|
|
|
Returns a dictionary of values to use when rendering the widget
|
|
template. By default, the dictionary contains a single key,
|
|
``'widget'``, which is a dictionary representation of the widget
|
|
containing the following keys:
|
|
|
|
* ``'name'``: The name of the field from the ``name`` argument.
|
|
* ``'is_hidden'``: A boolean indicating whether or not this widget is
|
|
hidden.
|
|
* ``'required'``: A boolean indicating whether or not the field for
|
|
this widget is required.
|
|
* ``'value'``: The value as returned by :meth:`format_value`.
|
|
* ``'attrs'``: HTML attributes to be set on the rendered widget. The
|
|
combination of the :attr:`attrs` attribute and the ``attrs`` argument.
|
|
* ``'template_name'``: The value of ``self.template_name``.
|
|
|
|
``Widget`` subclasses can provide custom context values by overriding
|
|
this method.
|
|
|
|
.. method:: id_for_label(id_)
|
|
|
|
Returns the HTML ID attribute of this widget for use by a ``<label>``,
|
|
given the ID of the field. Returns an empty string if an ID isn't
|
|
available.
|
|
|
|
This hook is necessary because some widgets have multiple HTML
|
|
elements and, thus, multiple IDs. In that case, this method should
|
|
return an ID value that corresponds to the first ID in the widget's
|
|
tags.
|
|
|
|
.. method:: render(name, value, attrs=None, renderer=None)
|
|
|
|
Renders a widget to HTML using the given renderer. If ``renderer`` is
|
|
``None``, the renderer from the :setting:`FORM_RENDERER` setting is
|
|
used.
|
|
|
|
.. method:: value_from_datadict(data, files, name)
|
|
|
|
Given a dictionary of data and this widget's name, returns the value
|
|
of this widget. ``files`` may contain data coming from
|
|
:attr:`request.FILES <django.http.HttpRequest.FILES>`. Returns ``None``
|
|
if a value wasn't provided. Note also that ``value_from_datadict`` may
|
|
be called more than once during handling of form data, so if you
|
|
customize it and add expensive processing, you should implement some
|
|
caching mechanism yourself.
|
|
|
|
.. method:: value_omitted_from_data(data, files, name)
|
|
|
|
Given ``data`` and ``files`` dictionaries and this widget's name,
|
|
returns whether or not there's data or files for the widget.
|
|
|
|
The method's result affects whether or not a field in a model form
|
|
:ref:`falls back to its default <topics-modelform-save>`.
|
|
|
|
Special cases are :class:`~django.forms.CheckboxInput`,
|
|
:class:`~django.forms.CheckboxSelectMultiple`, and
|
|
:class:`~django.forms.SelectMultiple`, which always return
|
|
``False`` because an unchecked checkbox and unselected
|
|
``<select multiple>`` don't appear in the data of an HTML form
|
|
submission, so it's unknown whether or not the user submitted a value.
|
|
|
|
.. attribute:: Widget.use_fieldset
|
|
|
|
An attribute to identify if the widget should be grouped in a
|
|
``<fieldset>`` with a ``<legend>`` when rendered. Defaults to ``False``
|
|
but is ``True`` when the widget contains multiple ``<input>`` tags such as
|
|
:class:`~django.forms.CheckboxSelectMultiple`,
|
|
:class:`~django.forms.RadioSelect`,
|
|
:class:`~django.forms.MultiWidget`,
|
|
:class:`~django.forms.SplitDateTimeWidget`, and
|
|
:class:`~django.forms.SelectDateWidget`.
|
|
|
|
.. method:: use_required_attribute(initial)
|
|
|
|
Given a form field's ``initial`` value, returns whether or not the
|
|
widget can be rendered with the ``required`` HTML attribute. Forms use
|
|
this method along with :attr:`Field.required
|
|
<django.forms.Field.required>` and :attr:`Form.use_required_attribute
|
|
<django.forms.Form.use_required_attribute>` to determine whether or not
|
|
to display the ``required`` attribute for each field.
|
|
|
|
By default, returns ``False`` for hidden widgets and ``True``
|
|
otherwise. Special cases are :class:`~django.forms.FileInput` and
|
|
:class:`~django.forms.ClearableFileInput`, which return ``False`` when
|
|
``initial`` is set, and :class:`~django.forms.CheckboxSelectMultiple`,
|
|
which always returns ``False`` because browser validation would require
|
|
all checkboxes to be checked instead of at least one.
|
|
|
|
Override this method in custom widgets that aren't compatible with
|
|
browser validation. For example, a WSYSIWG text editor widget backed by
|
|
a hidden ``textarea`` element may want to always return ``False`` to
|
|
avoid browser validation on the hidden field.
|
|
|
|
``MultiWidget``
|
|
---------------
|
|
|
|
.. class:: MultiWidget(widgets, attrs=None)
|
|
|
|
A widget that is composed of multiple widgets.
|
|
:class:`~django.forms.MultiWidget` works hand in hand with the
|
|
:class:`~django.forms.MultiValueField`.
|
|
|
|
:class:`MultiWidget` has one required argument:
|
|
|
|
.. attribute:: MultiWidget.widgets
|
|
|
|
An iterable containing the widgets needed. For example:
|
|
|
|
.. code-block:: pycon
|
|
|
|
>>> from django.forms import MultiWidget, TextInput
|
|
>>> widget = MultiWidget(widgets=[TextInput, TextInput])
|
|
>>> widget.render("name", ["john", "paul"])
|
|
'<input type="text" name="name_0" value="john"><input type="text" name="name_1" value="paul">'
|
|
|
|
You may provide a dictionary in order to specify custom suffixes for
|
|
the ``name`` attribute on each subwidget. In this case, for each
|
|
``(key, widget)`` pair, the key will be appended to the ``name`` of the
|
|
widget in order to generate the attribute value. You may provide the
|
|
empty string (``''``) for a single key, in order to suppress the suffix
|
|
for one widget. For example:
|
|
|
|
.. code-block:: pycon
|
|
|
|
>>> widget = MultiWidget(widgets={"": TextInput, "last": TextInput})
|
|
>>> widget.render("name", ["john", "paul"])
|
|
'<input type="text" name="name" value="john"><input type="text" name="name_last" value="paul">'
|
|
|
|
And one required method:
|
|
|
|
.. method:: decompress(value)
|
|
|
|
This method takes a single "compressed" value from the field and
|
|
returns a list of "decompressed" values. The input value can be
|
|
assumed valid, but not necessarily non-empty.
|
|
|
|
This method **must be implemented** by the subclass, and since the
|
|
value may be empty, the implementation must be defensive.
|
|
|
|
The rationale behind "decompression" is that it is necessary to "split"
|
|
the combined value of the form field into the values for each widget.
|
|
|
|
An example of this is how :class:`SplitDateTimeWidget` turns a
|
|
:class:`~datetime.datetime` value into a list with date and time split
|
|
into two separate values::
|
|
|
|
from django.forms import MultiWidget
|
|
|
|
|
|
class SplitDateTimeWidget(MultiWidget):
|
|
# ...
|
|
|
|
def decompress(self, value):
|
|
if value:
|
|
return [value.date(), value.time()]
|
|
return [None, None]
|
|
|
|
.. tip::
|
|
|
|
Note that :class:`~django.forms.MultiValueField` has a
|
|
complementary method :meth:`~django.forms.MultiValueField.compress`
|
|
with the opposite responsibility - to combine cleaned values of
|
|
all member fields into one.
|
|
|
|
It provides some custom context:
|
|
|
|
.. method:: get_context(name, value, attrs)
|
|
|
|
In addition to the ``'widget'`` key described in
|
|
:meth:`Widget.get_context`, ``MultiWidget`` adds a
|
|
``widget['subwidgets']`` key.
|
|
|
|
These can be looped over in the widget template:
|
|
|
|
.. code-block:: html+django
|
|
|
|
{% for subwidget in widget.subwidgets %}
|
|
{% include subwidget.template_name with widget=subwidget %}
|
|
{% endfor %}
|
|
|
|
Here's an example widget which subclasses :class:`MultiWidget` to display
|
|
a date with the day, month, and year in different select boxes. This widget
|
|
is intended to be used with a :class:`~django.forms.DateField` rather than
|
|
a :class:`~django.forms.MultiValueField`, thus we have implemented
|
|
:meth:`~Widget.value_from_datadict`::
|
|
|
|
from datetime import date
|
|
from django import forms
|
|
|
|
|
|
class DateSelectorWidget(forms.MultiWidget):
|
|
def __init__(self, attrs=None):
|
|
days = {day: day for day in range(1, 32)}
|
|
months = {month: month for month in range(1, 13)}
|
|
years = {year: year for year in [2018, 2019, 2020]}
|
|
widgets = [
|
|
forms.Select(attrs=attrs, choices=days),
|
|
forms.Select(attrs=attrs, choices=months),
|
|
forms.Select(attrs=attrs, choices=years),
|
|
]
|
|
super().__init__(widgets, attrs)
|
|
|
|
def decompress(self, value):
|
|
if isinstance(value, date):
|
|
return [value.day, value.month, value.year]
|
|
elif isinstance(value, str):
|
|
year, month, day = value.split("-")
|
|
return [day, month, year]
|
|
return [None, None, None]
|
|
|
|
def value_from_datadict(self, data, files, name):
|
|
day, month, year = super().value_from_datadict(data, files, name)
|
|
# DateField expects a single string that it can parse into a date.
|
|
return "{}-{}-{}".format(year, month, day)
|
|
|
|
The constructor creates several :class:`Select` widgets in a list. The
|
|
``super()`` method uses this list to set up the widget.
|
|
|
|
The required method :meth:`~MultiWidget.decompress` breaks up a
|
|
``datetime.date`` value into the day, month, and year values corresponding
|
|
to each widget. If an invalid date was selected, such as the non-existent
|
|
30th February, the :class:`~django.forms.DateField` passes this method a
|
|
string instead, so that needs parsing. The final ``return`` handles when
|
|
``value`` is ``None``, meaning we don't have any defaults for our
|
|
subwidgets.
|
|
|
|
The default implementation of :meth:`~Widget.value_from_datadict` returns a
|
|
list of values corresponding to each ``Widget``. This is appropriate when
|
|
using a ``MultiWidget`` with a :class:`~django.forms.MultiValueField`. But
|
|
since we want to use this widget with a :class:`~django.forms.DateField`,
|
|
which takes a single value, we have overridden this method. The
|
|
implementation here combines the data from the subwidgets into a string in
|
|
the format that :class:`~django.forms.DateField` expects.
|
|
|
|
.. _built-in widgets:
|
|
|
|
Built-in widgets
|
|
================
|
|
|
|
Django provides a representation of all the basic HTML widgets, plus some
|
|
commonly used groups of widgets in the ``django.forms.widgets`` module,
|
|
including :ref:`the input of text <text-widgets>`, :ref:`various checkboxes
|
|
and selectors <selector-widgets>`, :ref:`uploading files <file-upload-widgets>`,
|
|
and :ref:`handling of multi-valued input <composite-widgets>`.
|
|
|
|
.. _text-widgets:
|
|
|
|
Widgets handling input of text
|
|
------------------------------
|
|
|
|
These widgets make use of the HTML elements ``input`` and ``textarea``.
|
|
|
|
``TextInput``
|
|
~~~~~~~~~~~~~
|
|
|
|
.. class:: TextInput
|
|
|
|
* ``input_type``: ``'text'``
|
|
* ``template_name``: ``'django/forms/widgets/text.html'``
|
|
* Renders as: ``<input type="text" ...>``
|
|
|
|
``NumberInput``
|
|
~~~~~~~~~~~~~~~
|
|
|
|
.. class:: NumberInput
|
|
|
|
* ``input_type``: ``'number'``
|
|
* ``template_name``: ``'django/forms/widgets/number.html'``
|
|
* Renders as: ``<input type="number" ...>``
|
|
|
|
Beware that not all browsers support entering localized numbers in
|
|
``number`` input types. Django itself avoids using them for fields having
|
|
their :attr:`~django.forms.Field.localize` property set to ``True``.
|
|
|
|
``EmailInput``
|
|
~~~~~~~~~~~~~~
|
|
|
|
.. class:: EmailInput
|
|
|
|
* ``input_type``: ``'email'``
|
|
* ``template_name``: ``'django/forms/widgets/email.html'``
|
|
* Renders as: ``<input type="email" ...>``
|
|
|
|
``URLInput``
|
|
~~~~~~~~~~~~
|
|
|
|
.. class:: URLInput
|
|
|
|
* ``input_type``: ``'url'``
|
|
* ``template_name``: ``'django/forms/widgets/url.html'``
|
|
* Renders as: ``<input type="url" ...>``
|
|
|
|
``PasswordInput``
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
.. class:: PasswordInput
|
|
|
|
* ``input_type``: ``'password'``
|
|
* ``template_name``: ``'django/forms/widgets/password.html'``
|
|
* Renders as: ``<input type="password" ...>``
|
|
|
|
Takes one optional argument:
|
|
|
|
.. attribute:: PasswordInput.render_value
|
|
|
|
Determines whether the widget will have a value filled in when the
|
|
form is re-displayed after a validation error (default is ``False``).
|
|
|
|
``HiddenInput``
|
|
~~~~~~~~~~~~~~~
|
|
|
|
.. class:: HiddenInput
|
|
|
|
* ``input_type``: ``'hidden'``
|
|
* ``template_name``: ``'django/forms/widgets/hidden.html'``
|
|
* Renders as: ``<input type="hidden" ...>``
|
|
|
|
Note that there also is a :class:`MultipleHiddenInput` widget that
|
|
encapsulates a set of hidden input elements.
|
|
|
|
``DateInput``
|
|
~~~~~~~~~~~~~
|
|
|
|
.. class:: DateInput
|
|
|
|
* ``input_type``: ``'text'``
|
|
* ``template_name``: ``'django/forms/widgets/date.html'``
|
|
* Renders as: ``<input type="text" ...>``
|
|
|
|
Takes same arguments as :class:`TextInput`, with one more optional argument:
|
|
|
|
.. attribute:: DateInput.format
|
|
|
|
The format in which this field's initial value will be displayed.
|
|
|
|
If no ``format`` argument is provided, the default format is the first
|
|
format found in :setting:`DATE_INPUT_FORMATS` and respects
|
|
:doc:`/topics/i18n/formatting`. ``%U``, ``%W``, and ``%j`` formats are not
|
|
supported by this widget.
|
|
|
|
``DateTimeInput``
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
.. class:: DateTimeInput
|
|
|
|
* ``input_type``: ``'text'``
|
|
* ``template_name``: ``'django/forms/widgets/datetime.html'``
|
|
* Renders as: ``<input type="text" ...>``
|
|
|
|
Takes same arguments as :class:`TextInput`, with one more optional argument:
|
|
|
|
.. attribute:: DateTimeInput.format
|
|
|
|
The format in which this field's initial value will be displayed.
|
|
|
|
If no ``format`` argument is provided, the default format is the first
|
|
format found in :setting:`DATETIME_INPUT_FORMATS` and respects
|
|
:doc:`/topics/i18n/formatting`. ``%U``, ``%W``, and ``%j`` formats are not
|
|
supported by this widget.
|
|
|
|
By default, the microseconds part of the time value is always set to ``0``.
|
|
If microseconds are required, use a subclass with the
|
|
:attr:`~Widget.supports_microseconds` attribute set to ``True``.
|
|
|
|
``TimeInput``
|
|
~~~~~~~~~~~~~
|
|
|
|
.. class:: TimeInput
|
|
|
|
* ``input_type``: ``'text'``
|
|
* ``template_name``: ``'django/forms/widgets/time.html'``
|
|
* Renders as: ``<input type="text" ...>``
|
|
|
|
Takes same arguments as :class:`TextInput`, with one more optional argument:
|
|
|
|
.. attribute:: TimeInput.format
|
|
|
|
The format in which this field's initial value will be displayed.
|
|
|
|
If no ``format`` argument is provided, the default format is the first
|
|
format found in :setting:`TIME_INPUT_FORMATS` and respects
|
|
:doc:`/topics/i18n/formatting`.
|
|
|
|
For the treatment of microseconds, see :class:`DateTimeInput`.
|
|
|
|
``Textarea``
|
|
~~~~~~~~~~~~
|
|
|
|
.. class:: Textarea
|
|
|
|
* ``template_name``: ``'django/forms/widgets/textarea.html'``
|
|
* Renders as: ``<textarea>...</textarea>``
|
|
|
|
.. _selector-widgets:
|
|
|
|
Selector and checkbox widgets
|
|
-----------------------------
|
|
|
|
These widgets make use of the HTML elements ``<select>``,
|
|
``<input type="checkbox">``, and ``<input type="radio">``.
|
|
|
|
Widgets that render multiple choices have an ``option_template_name`` attribute
|
|
that specifies the template used to render each choice. For example, for the
|
|
:class:`Select` widget, ``select_option.html`` renders the ``<option>`` for a
|
|
``<select>``.
|
|
|
|
``CheckboxInput``
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
.. class:: CheckboxInput
|
|
|
|
* ``input_type``: ``'checkbox'``
|
|
* ``template_name``: ``'django/forms/widgets/checkbox.html'``
|
|
* Renders as: ``<input type="checkbox" ...>``
|
|
|
|
Takes one optional argument:
|
|
|
|
.. attribute:: CheckboxInput.check_test
|
|
|
|
A callable that takes the value of the ``CheckboxInput`` and returns
|
|
``True`` if the checkbox should be checked for that value.
|
|
|
|
``Select``
|
|
~~~~~~~~~~
|
|
|
|
.. class:: Select
|
|
|
|
* ``template_name``: ``'django/forms/widgets/select.html'``
|
|
* ``option_template_name``: ``'django/forms/widgets/select_option.html'``
|
|
* Renders as: ``<select><option ...>...</select>``
|
|
|
|
.. attribute:: Select.choices
|
|
|
|
This attribute is optional when the form field does not have a
|
|
``choices`` attribute. If it does, it will override anything you set
|
|
here when the attribute is updated on the :class:`Field`.
|
|
|
|
``NullBooleanSelect``
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
.. class:: NullBooleanSelect
|
|
|
|
* ``template_name``: ``'django/forms/widgets/select.html'``
|
|
* ``option_template_name``: ``'django/forms/widgets/select_option.html'``
|
|
|
|
Select widget with options 'Unknown', 'Yes' and 'No'
|
|
|
|
``SelectMultiple``
|
|
~~~~~~~~~~~~~~~~~~
|
|
|
|
.. class:: SelectMultiple
|
|
|
|
* ``template_name``: ``'django/forms/widgets/select.html'``
|
|
* ``option_template_name``: ``'django/forms/widgets/select_option.html'``
|
|
|
|
Similar to :class:`Select`, but allows multiple selection:
|
|
``<select multiple>...</select>``
|
|
|
|
``RadioSelect``
|
|
~~~~~~~~~~~~~~~
|
|
|
|
.. class:: RadioSelect
|
|
|
|
* ``template_name``: ``'django/forms/widgets/radio.html'``
|
|
* ``option_template_name``: ``'django/forms/widgets/radio_option.html'``
|
|
|
|
Similar to :class:`Select`, but rendered as a list of radio buttons within
|
|
``<div>`` tags:
|
|
|
|
.. code-block:: html
|
|
|
|
<div>
|
|
<div><input type="radio" name="..."></div>
|
|
...
|
|
</div>
|
|
|
|
For more granular control over the generated markup, you can loop over the
|
|
radio buttons in the template. Assuming a form ``myform`` with a field
|
|
``beatles`` that uses a ``RadioSelect`` as its widget:
|
|
|
|
.. code-block:: html+django
|
|
|
|
<fieldset>
|
|
<legend>{{ myform.beatles.label }}</legend>
|
|
{% for radio in myform.beatles %}
|
|
<div class="myradio">
|
|
{{ radio }}
|
|
</div>
|
|
{% endfor %}
|
|
</fieldset>
|
|
|
|
This would generate the following HTML:
|
|
|
|
.. code-block:: html
|
|
|
|
<fieldset>
|
|
<legend>Radio buttons</legend>
|
|
<div class="myradio">
|
|
<label for="id_beatles_0"><input id="id_beatles_0" name="beatles" type="radio" value="john" required> John</label>
|
|
</div>
|
|
<div class="myradio">
|
|
<label for="id_beatles_1"><input id="id_beatles_1" name="beatles" type="radio" value="paul" required> Paul</label>
|
|
</div>
|
|
<div class="myradio">
|
|
<label for="id_beatles_2"><input id="id_beatles_2" name="beatles" type="radio" value="george" required> George</label>
|
|
</div>
|
|
<div class="myradio">
|
|
<label for="id_beatles_3"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" required> Ringo</label>
|
|
</div>
|
|
</fieldset>
|
|
|
|
That included the ``<label>`` tags. To get more granular, you can use each
|
|
radio button's ``tag``, ``choice_label`` and ``id_for_label`` attributes.
|
|
For example, this template...
|
|
|
|
.. code-block:: html+django
|
|
|
|
<fieldset>
|
|
<legend>{{ myform.beatles.label }}</legend>
|
|
{% for radio in myform.beatles %}
|
|
<label for="{{ radio.id_for_label }}">
|
|
{{ radio.choice_label }}
|
|
<span class="radio">{{ radio.tag }}</span>
|
|
</label>
|
|
{% endfor %}
|
|
</fieldset>
|
|
|
|
...will result in the following HTML:
|
|
|
|
.. code-block:: html
|
|
|
|
<fieldset>
|
|
<legend>Radio buttons</legend>
|
|
<label for="id_beatles_0">
|
|
John
|
|
<span class="radio"><input id="id_beatles_0" name="beatles" type="radio" value="john" required></span>
|
|
</label>
|
|
<label for="id_beatles_1">
|
|
Paul
|
|
<span class="radio"><input id="id_beatles_1" name="beatles" type="radio" value="paul" required></span>
|
|
</label>
|
|
<label for="id_beatles_2">
|
|
George
|
|
<span class="radio"><input id="id_beatles_2" name="beatles" type="radio" value="george" required></span>
|
|
</label>
|
|
<label for="id_beatles_3">
|
|
Ringo
|
|
<span class="radio"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" required></span>
|
|
</label>
|
|
</fieldset>
|
|
|
|
If you decide not to loop over the radio buttons -- e.g., if your template
|
|
includes ``{{ myform.beatles }}`` -- they'll be output in a ``<div>`` with
|
|
``<div>`` tags, as above.
|
|
|
|
The outer ``<div>`` container receives the ``id`` attribute of the widget,
|
|
if defined, or :attr:`BoundField.auto_id` otherwise.
|
|
|
|
When looping over the radio buttons, the ``label`` and ``input`` tags include
|
|
``for`` and ``id`` attributes, respectively. Each radio button has an
|
|
``id_for_label`` attribute to output the element's ID.
|
|
|
|
``CheckboxSelectMultiple``
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
.. class:: CheckboxSelectMultiple
|
|
|
|
* ``template_name``: ``'django/forms/widgets/checkbox_select.html'``
|
|
* ``option_template_name``: ``'django/forms/widgets/checkbox_option.html'``
|
|
|
|
Similar to :class:`SelectMultiple`, but rendered as a list of checkboxes:
|
|
|
|
.. code-block:: html
|
|
|
|
<div>
|
|
<div><input type="checkbox" name="..." ></div>
|
|
...
|
|
</div>
|
|
|
|
The outer ``<div>`` container receives the ``id`` attribute of the widget,
|
|
if defined, or :attr:`BoundField.auto_id` otherwise.
|
|
|
|
Like :class:`RadioSelect`, you can loop over the individual checkboxes for the
|
|
widget's choices. Unlike :class:`RadioSelect`, the checkboxes won't include the
|
|
``required`` HTML attribute if the field is required because browser validation
|
|
would require all checkboxes to be checked instead of at least one.
|
|
|
|
When looping over the checkboxes, the ``label`` and ``input`` tags include
|
|
``for`` and ``id`` attributes, respectively. Each checkbox has an
|
|
``id_for_label`` attribute to output the element's ID.
|
|
|
|
.. _file-upload-widgets:
|
|
|
|
File upload widgets
|
|
-------------------
|
|
|
|
``FileInput``
|
|
~~~~~~~~~~~~~
|
|
|
|
.. class:: FileInput
|
|
|
|
* ``template_name``: ``'django/forms/widgets/file.html'``
|
|
* Renders as: ``<input type="file" ...>``
|
|
|
|
``ClearableFileInput``
|
|
~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
.. class:: ClearableFileInput
|
|
|
|
* ``template_name``: ``'django/forms/widgets/clearable_file_input.html'``
|
|
* Renders as: ``<input type="file" ...>`` with an additional checkbox
|
|
input to clear the field's value, if the field is not required and has
|
|
initial data.
|
|
|
|
.. _composite-widgets:
|
|
|
|
Composite widgets
|
|
-----------------
|
|
|
|
``MultipleHiddenInput``
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
.. class:: MultipleHiddenInput
|
|
|
|
* ``template_name``: ``'django/forms/widgets/multiple_hidden.html'``
|
|
* Renders as: multiple ``<input type="hidden" ...>`` tags
|
|
|
|
A widget that handles multiple hidden widgets for fields that have a list
|
|
of values.
|
|
|
|
``SplitDateTimeWidget``
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
.. class:: SplitDateTimeWidget
|
|
|
|
* ``template_name``: ``'django/forms/widgets/splitdatetime.html'``
|
|
|
|
Wrapper (using :class:`MultiWidget`) around two widgets: :class:`DateInput`
|
|
for the date, and :class:`TimeInput` for the time. Must be used with
|
|
:class:`SplitDateTimeField` rather than :class:`DateTimeField`.
|
|
|
|
``SplitDateTimeWidget`` has several optional arguments:
|
|
|
|
.. attribute:: SplitDateTimeWidget.date_format
|
|
|
|
Similar to :attr:`DateInput.format`
|
|
|
|
.. attribute:: SplitDateTimeWidget.time_format
|
|
|
|
Similar to :attr:`TimeInput.format`
|
|
|
|
.. attribute:: SplitDateTimeWidget.date_attrs
|
|
.. attribute:: SplitDateTimeWidget.time_attrs
|
|
|
|
Similar to :attr:`Widget.attrs`. A dictionary containing HTML
|
|
attributes to be set on the rendered :class:`DateInput` and
|
|
:class:`TimeInput` widgets, respectively. If these attributes aren't
|
|
set, :attr:`Widget.attrs` is used instead.
|
|
|
|
``SplitHiddenDateTimeWidget``
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
.. class:: SplitHiddenDateTimeWidget
|
|
|
|
* ``template_name``: ``'django/forms/widgets/splithiddendatetime.html'``
|
|
|
|
Similar to :class:`SplitDateTimeWidget`, but uses :class:`HiddenInput` for
|
|
both date and time.
|
|
|
|
``SelectDateWidget``
|
|
~~~~~~~~~~~~~~~~~~~~
|
|
|
|
.. class:: SelectDateWidget
|
|
|
|
* ``template_name``: ``'django/forms/widgets/select_date.html'``
|
|
|
|
Wrapper around three :class:`~django.forms.Select` widgets: one each for
|
|
month, day, and year.
|
|
|
|
Takes several optional arguments:
|
|
|
|
.. attribute:: SelectDateWidget.years
|
|
|
|
An optional list/tuple of years to use in the "year" select box.
|
|
The default is a list containing the current year and the next 9 years.
|
|
|
|
.. attribute:: SelectDateWidget.months
|
|
|
|
An optional dict of months to use in the "months" select box.
|
|
|
|
The keys of the dict correspond to the month number (1-indexed) and
|
|
the values are the displayed months::
|
|
|
|
MONTHS = {
|
|
1: _("jan"),
|
|
2: _("feb"),
|
|
3: _("mar"),
|
|
4: _("apr"),
|
|
5: _("may"),
|
|
6: _("jun"),
|
|
7: _("jul"),
|
|
8: _("aug"),
|
|
9: _("sep"),
|
|
10: _("oct"),
|
|
11: _("nov"),
|
|
12: _("dec"),
|
|
}
|
|
|
|
.. attribute:: SelectDateWidget.empty_label
|
|
|
|
If the :class:`~django.forms.DateField` is not required,
|
|
:class:`SelectDateWidget` will have an empty choice at the top of the
|
|
list (which is ``---`` by default). You can change the text of this
|
|
label with the ``empty_label`` attribute. ``empty_label`` can be a
|
|
``string``, ``list``, or ``tuple``. When a string is used, all select
|
|
boxes will each have an empty choice with this label. If ``empty_label``
|
|
is a ``list`` or ``tuple`` of 3 string elements, the select boxes will
|
|
have their own custom label. The labels should be in this order
|
|
``('year_label', 'month_label', 'day_label')``.
|
|
|
|
.. code-block:: python
|
|
|
|
# A custom empty label with string
|
|
field1 = forms.DateField(widget=SelectDateWidget(empty_label="Nothing"))
|
|
|
|
# A custom empty label with tuple
|
|
field1 = forms.DateField(
|
|
widget=SelectDateWidget(
|
|
empty_label=("Choose Year", "Choose Month", "Choose Day"),
|
|
),
|
|
)
|