123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831 |
- =======
- 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.
- .. 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" /></td></tr>
- <tr><th>Url:</th><td><input type="url" name="url"/></td></tr>
- <tr><th>Comment:</th><td><input type="text" name="comment" /></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"/></td></tr>
- <tr><th>Url:</th><td><input type="url" name="url"/></td></tr>
- <tr><th>Comment:</th><td><input type="text" name="comment" size="40"/></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.
- .. 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" />'
- .. versionchanged:: 1.8
- 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``.
- .. versionadded:: 1.9
- In older versions, this attribute was only defined on the date
- and time widgets (as ``False``).
- .. method:: render(name, value, attrs=None)
- Returns HTML for the widget, as a Unicode string. This method must be
- implemented by the subclass, otherwise ``NotImplementedError`` will be
- raised.
- The 'value' given is not guaranteed to be valid input, therefore
- subclass implementations should program defensively.
- .. 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.
- .. 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().replace(microsecond=0)]
- 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.
- Other methods that may be useful to override include:
- .. method:: render(name, value, attrs=None)
- Argument ``value`` is handled differently in this method from the
- subclasses of :class:`~Widget` because it has to figure out how to
- split a single value for display in multiple widgets.
- The ``value`` argument used when rendering can be one of two things:
- * A ``list``.
- * A single value (e.g., a string) that is the "compressed" representation
- of a ``list`` of values.
- If ``value`` is a list, the output of :meth:`~MultiWidget.render` will
- be a concatenation of rendered child widgets. If ``value`` is not a
- list, it will first be processed by the method
- :meth:`~MultiWidget.decompress()` to create the list and then rendered.
- When ``render()`` executes its HTML rendering, each value in the list
- is rendered with the corresponding widget -- the first value is
- rendered in the first widget, the second value is rendered in the
- second widget, etc.
- Unlike in the single value widgets, method :meth:`~MultiWidget.render`
- need not be implemented in the subclasses.
- .. method:: format_output(rendered_widgets)
- Given a list of rendered widgets (as strings), returns a Unicode string
- representing the HTML for the whole lot.
- This hook allows you to format the HTML design of the widgets any way
- you'd like.
- 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(DateSelectorWidget, self).__init__(_widgets, attrs)
- def decompress(self, value):
- if value:
- return [value.day, value.month, value.year]
- return [None, None, None]
- def format_output(self, rendered_widgets):
- return ''.join(rendered_widgets)
- 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 :meth:`~MultiWidget.format_output` method is fairly vanilla here (in
- fact, it's the same as what's been implemented as the default for
- ``MultiWidget``), but the idea is that you could add custom HTML between
- the widgets should you wish.
- 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
- Text input: ``<input type="text" ...>``
- ``NumberInput``
- ~~~~~~~~~~~~~~~
- .. class:: NumberInput
- Text input: ``<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
- Text input: ``<input type="email" ...>``
- ``URLInput``
- ~~~~~~~~~~~~
- .. class:: URLInput
- Text input: ``<input type="url" ...>``
- ``PasswordInput``
- ~~~~~~~~~~~~~~~~~
- .. class:: PasswordInput
- Password input: ``<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
- Hidden input: ``<input type='hidden' ...>``
- Note that there also is a :class:`MultipleHiddenInput` widget that
- encapsulates a set of hidden input elements.
- ``DateInput``
- ~~~~~~~~~~~~~
- .. class:: DateInput
- Date input as a simple text box: ``<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
- :ref:`format-localization`.
- ``DateTimeInput``
- ~~~~~~~~~~~~~~~~~
- .. class:: DateTimeInput
- Date/time input as a simple text box: ``<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
- :ref:`format-localization`.
- 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
- Time input as a simple text box: ``<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
- :ref:`format-localization`.
- For the treatment of microseconds, see :class:`DateTimeInput`.
- ``Textarea``
- ~~~~~~~~~~~~
- .. class:: Textarea
- Text area: ``<textarea>...</textarea>``
- .. _selector-widgets:
- Selector and checkbox widgets
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- ``CheckboxInput``
- ~~~~~~~~~~~~~~~~~
- .. class:: CheckboxInput
- Checkbox: ``<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
- Select widget: ``<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
- Select widget with options 'Unknown', 'Yes' and 'No'
- ``SelectMultiple``
- ~~~~~~~~~~~~~~~~~~
- .. class:: SelectMultiple
- Similar to :class:`Select`, but allows multiple selection:
- ``<select multiple='multiple'>...</select>``
- ``RadioSelect``
- ~~~~~~~~~~~~~~~
- .. class:: RadioSelect
- 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" /> John</label>
- </div>
- <div class="myradio">
- <label for="id_beatles_1"><input id="id_beatles_1" name="beatles" type="radio" value="paul" /> Paul</label>
- </div>
- <div class="myradio">
- <label for="id_beatles_2"><input id="id_beatles_2" name="beatles" type="radio" value="george" /> George</label>
- </div>
- <div class="myradio">
- <label for="id_beatles_3"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" /> 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" /></span>
- </label>
- <label for="id_beatles_1">
- Paul
- <span class="radio"><input id="id_beatles_1" name="beatles" type="radio" value="paul" /></span>
- </label>
- <label for="id_beatles_2">
- George
- <span class="radio"><input id="id_beatles_2" name="beatles" type="radio" value="george" /></span>
- </label>
- <label for="id_beatles_3">
- Ringo
- <span class="radio"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" /></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 will receive the ``id`` attribute defined on
- the widget.
- 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
- 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 will receive the ``id`` attribute defined on
- the widget.
- Like :class:`RadioSelect`, you can now loop over the individual checkboxes making
- up the lists. See the documentation of :class:`RadioSelect` for more details.
- 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
- File upload input: ``<input type='file' ...>``
- ``ClearableFileInput``
- ~~~~~~~~~~~~~~~~~~~~~~
- .. class:: ClearableFileInput
- File upload input: ``<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
- Multiple ``<input type='hidden' ...>`` widgets.
- 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
- Wrapper (using :class:`MultiWidget`) around two widgets: :class:`DateInput`
- for the date, and :class:`TimeInput` for the time.
- ``SplitDateTimeWidget`` has two optional attributes:
- .. attribute:: SplitDateTimeWidget.date_format
- Similar to :attr:`DateInput.format`
- .. attribute:: SplitDateTimeWidget.time_format
- Similar to :attr:`TimeInput.format`
- ``SplitHiddenDateTimeWidget``
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- .. class:: SplitHiddenDateTimeWidget
- Similar to :class:`SplitDateTimeWidget`, but uses :class:`HiddenInput` for
- both date and time.
- ``SelectDateWidget``
- ~~~~~~~~~~~~~~~~~~~~
- .. class:: SelectDateWidget
- Wrapper around three :class:`~django.forms.Select` widgets: one each for
- month, day, and year. Note that this widget lives in a separate file from
- the standard widgets.
- Takes one optional argument:
- .. 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
- .. versionadded:: 1.8
- 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"),
- ),
- )
- .. versionchanged:: 1.9
- This widget used to be located in the ``django.forms.extras.widgets``
- package. It is now defined in ``django.forms.widgets`` and like the
- other widgets it can be imported directly from ``django.forms``.
|