mirror of
				https://github.com/django/django.git
				synced 2025-10-28 08:06:09 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			529 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			529 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| =======
 | |
| 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.
 | |
| 
 | |
| 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 the bare minimum
 | |
| HTML - Django doesn't add a class definition, or any other widget-specific
 | |
| attributes. This means that all :class:`TextInput` widgets will appear the same
 | |
| on your Web page.
 | |
| 
 | |
| If you want to make one widget look different to another, you need to
 | |
| specify additional attributes for each widget. When you specify a
 | |
| widget, you can provide a list of attributes that will be added to the
 | |
| rendered HTML for the widget.
 | |
| 
 | |
| 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:
 | |
| 
 | |
| For example::
 | |
| 
 | |
|     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>
 | |
| 
 | |
| .. _built-in widgets:
 | |
| 
 | |
| Built-in widgets
 | |
| ----------------
 | |
| 
 | |
| Django provides a representation of all the basic HTML widgets, plus some
 | |
| commonly used groups of widgets:
 | |
| 
 | |
| ``Widget``
 | |
| ~~~~~~~~~~
 | |
| 
 | |
| .. class:: Widget
 | |
| 
 | |
|     This abstract class cannot be rendered, but provides the basic attribute :attr:`~Widget.attrs`.
 | |
| 
 | |
|     .. 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" />'
 | |
| 
 | |
| ``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' ...>``
 | |
| 
 | |
| ``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`.
 | |
| 
 | |
| ``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.
 | |
| 
 | |
| ``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>``
 | |
| 
 | |
| ``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>
 | |
| 
 | |
| ``MultiWidget``
 | |
| ~~~~~~~~~~~~~~~
 | |
| 
 | |
| .. class:: MultiWidget
 | |
| 
 | |
|     Wrapper around multiple other widgets. You'll probably want to use this
 | |
|     class with :class:`MultiValueField`.
 | |
| 
 | |
|     Its ``render()`` method is different than other widgets', because it has to
 | |
|     figure out how to split a single value for display in multiple widgets.
 | |
| 
 | |
|     Subclasses may implement ``format_output``, which takes the list of
 | |
|     rendered widgets and returns a string of HTML that formats them any way
 | |
|     you'd like.
 | |
| 
 | |
|     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.
 | |
| 
 | |
|     In the second case -- i.e., if the value is *not* a list -- ``render()``
 | |
|     will first decompress the value into a ``list`` before rendering it. It
 | |
|     does so by calling the ``decompress()`` method, which
 | |
|     :class:`MultiWidget`'s subclasses must implement. This method takes a
 | |
|     single "compressed" value and returns a ``list``. An example of this is how
 | |
|     :class:`SplitDateTimeWidget` turns a :class:`datetime` value into a list
 | |
|     with date and time split into two seperate values::
 | |
| 
 | |
|         class SplitDateTimeWidget(MultiWidget):
 | |
| 
 | |
|             # ...
 | |
| 
 | |
|             def decompress(self, value):
 | |
|                 if value:
 | |
|                     return [value.date(), value.time().replace(microsecond=0)]
 | |
|                 return [None, None]
 | |
| 
 | |
|     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.
 | |
| 
 | |
|     :class:`MultiWidget` has one required argument:
 | |
| 
 | |
|     .. attribute:: MultiWidget.widgets
 | |
| 
 | |
|         An iterable containing the widgets needed.
 | |
| 
 | |
| ``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.
 |