933 lines
33 KiB
Plaintext
933 lines
33 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
|
|
just 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::
|
|
|
|
>>> 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 simple 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::
|
|
|
|
>>> f = CommentForm(auto_id=False)
|
|
>>> f.as_table()
|
|
<tr><th>Name:</th><td><input type="text" name="name" required></td></tr>
|
|
<tr><th>Url:</th><td><input type="url" name="url" required></td></tr>
|
|
<tr><th>Comment:</th><td><input type="text" name="comment" required></td></tr>
|
|
|
|
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'}))
|
|
|
|
Django will then include the extra attributes in the rendered output:
|
|
|
|
>>> f = CommentForm(auto_id=False)
|
|
>>> f.as_table()
|
|
<tr><th>Name:</th><td><input type="text" name="name" class="special" required></td></tr>
|
|
<tr><th>Url:</th><td><input type="url" name="url" required></td></tr>
|
|
<tr><th>Comment:</th><td><input type="text" name="comment" size="40" required></td></tr>
|
|
|
|
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" required>'
|
|
|
|
If you assign a value of ``True`` or ``False`` to an attribute,
|
|
it will be rendered as an HTML5 boolean attribute::
|
|
|
|
>>> 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 ``None`` 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.
|
|
|
|
.. 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.ClearableFileInput`,
|
|
which returns ``False`` when ``initial`` is not 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.
|
|
|
|
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`, ``MultiValueWidget`` adds a
|
|
``widget['subwidgets']`` key.
|
|
|
|
These can be looped over in the widget template:
|
|
|
|
.. code-block:: html+django
|
|
|
|
{% for subwidget in widget.subwidgets %}
|
|
{% include widget.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.forms import widgets
|
|
|
|
class DateSelectorWidget(widgets.MultiWidget):
|
|
def __init__(self, attrs=None):
|
|
# create choices for days, months, years
|
|
# example below, the rest snipped for brevity.
|
|
years = [(year, year) for year in (2011, 2012, 2013)]
|
|
_widgets = (
|
|
widgets.Select(attrs=attrs, choices=days),
|
|
widgets.Select(attrs=attrs, choices=months),
|
|
widgets.Select(attrs=attrs, choices=years),
|
|
)
|
|
super().__init__(_widgets, attrs)
|
|
|
|
def decompress(self, value):
|
|
if value:
|
|
return [value.day, value.month, value.year]
|
|
return [None, None, None]
|
|
|
|
def value_from_datadict(self, data, files, name):
|
|
datelist = [
|
|
widget.value_from_datadict(data, files, name + '_%s' % i)
|
|
for i, widget in enumerate(self.widgets)]
|
|
try:
|
|
D = date(
|
|
day=int(datelist[0]),
|
|
month=int(datelist[1]),
|
|
year=int(datelist[2]),
|
|
)
|
|
except ValueError:
|
|
return ''
|
|
else:
|
|
return str(D)
|
|
|
|
The constructor creates several :class:`Select` widgets in a tuple. The
|
|
``super`` class uses this tuple to setup 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. Note how the method handles the case where ``value`` is
|
|
``None``.
|
|
|
|
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 to combine the
|
|
data of all the subwidgets into a ``datetime.date``. The method extracts
|
|
data from the ``POST`` dictionary and constructs and validates the date.
|
|
If it is valid, we return the string, otherwise, we return an empty string
|
|
which will cause ``form.is_valid`` to return ``False``.
|
|
|
|
.. _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`.
|
|
|
|
``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`.
|
|
|
|
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
|
|
``<li>`` tags:
|
|
|
|
.. code-block:: html
|
|
|
|
<ul>
|
|
<li><input type="radio" name="..."></li>
|
|
...
|
|
</ul>
|
|
|
|
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
|
|
|
|
{% for radio in myform.beatles %}
|
|
<div class="myradio">
|
|
{{ radio }}
|
|
</div>
|
|
{% endfor %}
|
|
|
|
This would generate the following HTML:
|
|
|
|
.. code-block:: html
|
|
|
|
<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>
|
|
|
|
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
|
|
|
|
{% for radio in myform.beatles %}
|
|
<label for="{{ radio.id_for_label }}">
|
|
{{ radio.choice_label }}
|
|
<span class="radio">{{ radio.tag }}</span>
|
|
</label>
|
|
{% endfor %}
|
|
|
|
...will result in the following HTML:
|
|
|
|
.. code-block:: html
|
|
|
|
<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>
|
|
|
|
If you decide not to loop over the radio buttons -- e.g., if your template
|
|
simply includes ``{{ myform.beatles }}`` -- they'll be output in a ``<ul>``
|
|
with ``<li>`` tags, as above.
|
|
|
|
The outer ``<ul>`` 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 check
|
|
buttons:
|
|
|
|
.. code-block:: html
|
|
|
|
<ul>
|
|
<li><input type="checkbox" name="..." ></li>
|
|
...
|
|
</ul>
|
|
|
|
The outer ``<ul>`` 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.
|
|
|
|
.. attribute:: MultipleHiddenInput.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`.
|
|
|
|
``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
|
|
|
|
.. versionadded:: 2.0
|
|
|
|
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"),
|
|
),
|
|
)
|