123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041 |
- =======
- 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 :class:`TextInput` widgets for the name and comment
- fields, and a :class:`URLInput` widget for the url field. Each has default
- rendering - no CSS class, no extra attributes:
- .. 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 want to customize this. 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 use a different HTML5 input type. 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" ...>``
- ``ColorInput``
- ~~~~~~~~~~~~~~
- .. versionadded:: 5.2
- .. class:: ColorInput
- * ``input_type``: ``'color'``
- * ``template_name``:``'django/forms/widgets/color.html'``
- * Renders as: ``<input type="color" ...>``
- ``SearchInput``
- ~~~~~~~~~~~~~~~
- .. versionadded:: 5.2
- .. class:: SearchInput
- * ``input_type``: ``'search'``
- * ``template_name``: ``'django/forms/widgets/search.html'``
- * Renders as: ``<input type="search" ...>``
- ``TelInput``
- ~~~~~~~~~~~~
- .. versionadded:: 5.2
- .. class:: TelInput
- * ``input_type``: ``'tel'``
- * ``template_name``: ``'django/forms/widgets/tel.html'``
- * Renders as: ``<input type="tel" ...>``
- Browsers perform no client-side validation by default because telephone
- number formats vary so much around the world. You can add some by setting
- ``pattern``, ``minlength``, or ``maxlength`` in the :attr:`Widget.attrs`
- argument.
- Additionally, you can add server-side validation to your form field with a
- validator like :class:`~django.core.validators.RegexValidator` or via
- third-party packages, such as :pypi:`django-phonenumber-field`.
- ``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"),
- ),
- )
|