| ======= |
| Widgets |
| ======= |
| |
| .. module:: django.forms.widgets |
| :synopsis: Django's built-in form widgets. |
| |
| .. currentmodule:: django.forms |
| |
| A widget is Django's representation of a 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:`~SelectDateWidget.years` attribute is set for a |
| :class:`~django.forms.extras.widgets.SelectDateWidget`:: |
| |
| from django.forms.fields import DateField, ChoiceField, MultipleChoiceField |
| from django.forms.widgets import RadioSelect, CheckboxSelectMultiple |
| from django.forms.extras.widgets import SelectDateWidget |
| |
| BIRTH_YEAR_CHOICES = ('1980', '1981', '1982') |
| FAVORITE_COLORS_CHOICES = (('blue', 'Blue'), |
| ('green', 'Green'), |
| ('black', 'Black')) |
| |
| class SimpleForm(forms.Form): |
| birth_year = DateField(widget=SelectDateWidget(years=BIRTH_YEAR_CHOICES)) |
| favorite_colors = forms.MultipleChoiceField(required=False, |
| widget=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="text" 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. 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="text" name="url"/></td></tr> |
| <tr><th>Comment:</th><td><input type="text" name="comment" size="40"/></td></tr> |
| |
| .. _styling-widget-classes: |
| |
| Styling widget classes |
| ^^^^^^^^^^^^^^^^^^^^^^ |
| |
| With widgets, it is possible to add media (``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 class "Media" <media-as-a-static-definition>` as a member of the |
| subclass, or :ref:`create a property "media" <dynamic-property>`, returning an |
| instance of that class. |
| |
| These methods involve somewhat advanced Python programming and are described in |
| detail in the :doc:`Form Media </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:: python |
| |
| >>> name = forms.TextInput(attrs={'size': 10, 'title': 'Your name',}) |
| >>> name.render('name', 'A name') |
| u'<input title="Your name" type="text" name="name" value="A name" size="10" />' |
| |
| .. 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(self, data, files, name) |
| |
| Given a dictionary of data and this widget's name, returns the value |
| of this widget. Returns ``None`` if a value wasn't provided. |
| |
| .. class:: MultiWidget(widgets, attrs=None) |
| |
| A widget that is composed of multiple widgets. |
| :class:`~django.forms.widgets.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` value into a list with date and time split into two |
| separate values:: |
| |
| 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 u''.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' ...>`` |
| |
| ``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``). |
| |
| .. versionchanged:: 1.3 |
| The default value for |
| :attr:`~PasswordInput.render_value` was |
| changed from ``True`` to ``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 one 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 one 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`. |
| |
| ``TimeInput`` |
| ~~~~~~~~~~~~~ |
| |
| .. class:: TimeInput |
| |
| Time input as a simple text box: ``<input type='text' ...>`` |
| |
| Takes one 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`. |
| |
| ``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 field does not have a |
| :attr:`~Field.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' ...></li> |
| ... |
| </ul> |
| |
| .. versionadded:: 1.4 |
| |
| 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><input type="radio" name="beatles" value="john" /> John</label> |
| </div> |
| <div class="myradio"> |
| <label><input type="radio" name="beatles" value="paul" /> Paul</label> |
| </div> |
| <div class="myradio"> |
| <label><input type="radio" name="beatles" value="george" /> George</label> |
| </div> |
| <div class="myradio"> |
| <label><input type="radio" name="beatles" value="ringo" /> Ringo</label> |
| </div> |
| |
| That included the ``<label>`` tags. To get more granular, you can use each |
| radio button's ``tag`` and ``choice_label`` attributes. For example, this template... |
| |
| .. code-block:: html+django |
| |
| {% for radio in myform.beatles %} |
| <label> |
| {{ radio.choice_label }} |
| <span class="radio">{{ radio.tag }}</span> |
| </label> |
| {% endfor %} |
| |
| ...will result in the following HTML: |
| |
| .. code-block:: html |
| |
| <label> |
| John |
| <span class="radio"><input type="radio" name="beatles" value="john" /></span> |
| </label> |
| <label> |
| Paul |
| <span class="radio"><input type="radio" name="beatles" value="paul" /></span> |
| </label> |
| <label> |
| George |
| <span class="radio"><input type="radio" name="beatles" value="george" /></span> |
| </label> |
| <label> |
| Ringo |
| <span class="radio"><input type="radio" name="beatles" 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. |
| |
| ``CheckboxSelectMultiple`` |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| .. class:: CheckboxSelectMultiple |
| |
| Similar to :class:`SelectMultiple`, but rendered as a list of check |
| buttons: |
| |
| .. code-block:: html |
| |
| <ul> |
| <li><input type='checkbox' ...></li> |
| ... |
| </ul> |
| |
| .. _file-upload-widgets: |
| |
| File upload widgets |
| ^^^^^^^^^^^^^^^^^^^ |
| |
| ``FileInput`` |
| ~~~~~~~~~~~~~ |
| |
| .. class:: FileInput |
| |
| File upload input: ``<input type='file' ...>`` |
| |
| ``ClearableFileInput`` |
| ~~~~~~~~~~~~~~~~~~~~~~ |
| |
| .. class:: ClearableFileInput |
| |
| .. versionadded:: 1.3 |
| |
| 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 field does not have a |
| :attr:`~Field.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. |
| |
| .. currentmodule:: django.forms.extras.widgets |
| |
| ``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. |