Fixed #16264 -- Improved form widget documentation. Many thanks to Bas Peschier.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@16408 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
e008fde23e
commit
662b372d02
|
@ -278,6 +278,7 @@ as the rendered output.
|
||||||
See the :ref:`format localization <format-localization>` documentation for
|
See the :ref:`format localization <format-localization>` documentation for
|
||||||
more information.
|
more information.
|
||||||
|
|
||||||
|
.. _built-in fields:
|
||||||
|
|
||||||
Built-in ``Field`` classes
|
Built-in ``Field`` classes
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
|
@ -11,9 +11,181 @@ 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
|
handles the rendering of the HTML, and the extraction of data from a GET/POST
|
||||||
dictionary that corresponds to the widget.
|
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:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
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.widgets.extras.SelectDateWidget`:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from django.forms.fields import DateField, ChoiceField, MultipleChoiceField
|
||||||
|
from django.forms.widgets import RadioSelect, CheckboxSelectMultiple
|
||||||
|
from django.forms.widgets.extras import SelectDateWidget
|
||||||
|
|
||||||
|
BIRTH_YEAR_CHOICES = ('1980', '1981', '1982')
|
||||||
|
GENDER_CHOICES = (('m', 'Male'), ('f', 'Female'))
|
||||||
|
FAVOURITE_COLORS_CHOICES = (('blue', 'Blue'),
|
||||||
|
('green', 'Green'),
|
||||||
|
('black', 'Black'))
|
||||||
|
|
||||||
|
class SimpleForm(forms.Form):
|
||||||
|
birth_year = DateField(widget=SelectDateWidget(years=YEAR_CHOICES))
|
||||||
|
gender = ChoiceField(widget=RadioSelect, choices=RADIO_CHOICES)
|
||||||
|
favourite_colors = forms.MultipleChoiceField(required=False,
|
||||||
|
widget=CheckboxSelectMultiple, choices=CHECKBOX_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:: python
|
||||||
|
|
||||||
|
>>> 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:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
>>> 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:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
>>> 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
|
Django provides a representation of all the basic HTML widgets, plus some
|
||||||
commonly used groups of widgets:
|
commonly used groups of widgets:
|
||||||
|
|
||||||
|
.. 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" />'
|
||||||
|
|
||||||
|
|
||||||
.. class:: TextInput
|
.. class:: TextInput
|
||||||
|
|
||||||
Text input: ``<input type='text' ...>``
|
Text input: ``<input type='text' ...>``
|
||||||
|
@ -29,10 +201,10 @@ commonly used groups of widgets:
|
||||||
Determines whether the widget will have a value filled in when the
|
Determines whether the widget will have a value filled in when the
|
||||||
form is re-displayed after a validation error (default is ``False``).
|
form is re-displayed after a validation error (default is ``False``).
|
||||||
|
|
||||||
.. versionchanged:: 1.3
|
.. versionchanged:: 1.3
|
||||||
The default value for
|
The default value for
|
||||||
:attr:`~PasswordInput.render_value` was
|
:attr:`~PasswordInput.render_value` was
|
||||||
changed from ``True`` to ``False``
|
changed from ``True`` to ``False``
|
||||||
|
|
||||||
.. class:: HiddenInput
|
.. class:: HiddenInput
|
||||||
|
|
||||||
|
@ -42,6 +214,15 @@ commonly used groups of widgets:
|
||||||
|
|
||||||
Multiple ``<input type='hidden' ...>`` widgets.
|
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`.
|
||||||
|
|
||||||
.. class:: FileInput
|
.. class:: FileInput
|
||||||
|
|
||||||
File upload input: ``<input type='file' ...>``
|
File upload input: ``<input type='file' ...>``
|
||||||
|
@ -64,7 +245,9 @@ commonly used groups of widgets:
|
||||||
|
|
||||||
The format in which this field's initial value will be displayed.
|
The format in which this field's initial value will be displayed.
|
||||||
|
|
||||||
If no ``format`` argument is provided, the default format is ``'%Y-%m-%d'``.
|
If no ``format`` argument is provided, the default format is the first
|
||||||
|
format found in :setting:`DATE_INPUT_FORMATS` and respects
|
||||||
|
:ref:`format-localization`.
|
||||||
|
|
||||||
.. class:: DateTimeInput
|
.. class:: DateTimeInput
|
||||||
|
|
||||||
|
@ -76,8 +259,9 @@ commonly used groups of widgets:
|
||||||
|
|
||||||
The format in which this field's initial value will be displayed.
|
The format in which this field's initial value will be displayed.
|
||||||
|
|
||||||
If no ``format`` argument is provided, the default format is ``'%Y-%m-%d
|
If no ``format`` argument is provided, the default format is the first
|
||||||
%H:%M:%S'``.
|
format found in :setting:`DATETIME_INPUT_FORMATS` and respects
|
||||||
|
:ref:`format-localization`.
|
||||||
|
|
||||||
.. class:: TimeInput
|
.. class:: TimeInput
|
||||||
|
|
||||||
|
@ -89,7 +273,9 @@ commonly used groups of widgets:
|
||||||
|
|
||||||
The format in which this field's initial value will be displayed.
|
The format in which this field's initial value will be displayed.
|
||||||
|
|
||||||
If no ``format`` argument is provided, the default format is ``'%H:%M:%S'``.
|
If no ``format`` argument is provided, the default format is the first
|
||||||
|
format found in :setting:`TIME_INPUT_FORMATS` and respects
|
||||||
|
:ref:`format-localization`.
|
||||||
|
|
||||||
.. class:: Textarea
|
.. class:: Textarea
|
||||||
|
|
||||||
|
@ -103,15 +289,18 @@ commonly used groups of widgets:
|
||||||
|
|
||||||
.. attribute:: CheckboxInput.check_test
|
.. attribute:: CheckboxInput.check_test
|
||||||
|
|
||||||
A callable that takes the value of the CheckBoxInput
|
A callable that takes the value of the CheckBoxInput and returns
|
||||||
and returns ``True`` if the checkbox should be checked for
|
``True`` if the checkbox should be checked for that value.
|
||||||
that value.
|
|
||||||
|
|
||||||
.. class:: Select
|
.. class:: Select
|
||||||
|
|
||||||
Select widget: ``<select><option ...>...</select>``
|
Select widget: ``<select><option ...>...</select>``
|
||||||
|
|
||||||
Requires that your field provides :attr:`~Field.choices`.
|
.. 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`.
|
||||||
|
|
||||||
.. class:: NullBooleanSelect
|
.. class:: NullBooleanSelect
|
||||||
|
|
||||||
|
@ -119,14 +308,12 @@ commonly used groups of widgets:
|
||||||
|
|
||||||
.. class:: SelectMultiple
|
.. class:: SelectMultiple
|
||||||
|
|
||||||
Select widget allowing multiple selection: ``<select
|
Similar to :class:`Select`, but allows multiple selection:
|
||||||
multiple='multiple'>...</select>``
|
``<select multiple='multiple'>...</select>``
|
||||||
|
|
||||||
Requires that your field provides :attr:`~Field.choices`.
|
|
||||||
|
|
||||||
.. class:: RadioSelect
|
.. class:: RadioSelect
|
||||||
|
|
||||||
A list of radio buttons:
|
Similar to :class:`Select`, but rendered as a list of radio buttons:
|
||||||
|
|
||||||
.. code-block:: html
|
.. code-block:: html
|
||||||
|
|
||||||
|
@ -135,11 +322,10 @@ commonly used groups of widgets:
|
||||||
...
|
...
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
Requires that your field provides :attr:`~Field.choices`.
|
|
||||||
|
|
||||||
.. class:: CheckboxSelectMultiple
|
.. class:: CheckboxSelectMultiple
|
||||||
|
|
||||||
A list of checkboxes:
|
Similar to :class:`SelectMultiple`, but rendered as a list of check
|
||||||
|
buttons:
|
||||||
|
|
||||||
.. code-block:: html
|
.. code-block:: html
|
||||||
|
|
||||||
|
@ -150,111 +336,83 @@ commonly used groups of widgets:
|
||||||
|
|
||||||
.. class:: MultiWidget
|
.. class:: MultiWidget
|
||||||
|
|
||||||
Wrapper around multiple other widgets
|
Wrapper around multiple other widgets. You'll probably want to use this
|
||||||
|
class with :class:`MultiValueField`.
|
||||||
|
|
||||||
.. class:: SplitDateTimeWidget
|
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.
|
||||||
|
|
||||||
Wrapper around two widgets: ``DateInput`` for the date, and ``TimeInput``
|
Subclasses may implement ``format_output``, which takes the list of
|
||||||
for the time.
|
rendered widgets and returns a string of HTML that formats them any way
|
||||||
|
you'd like.
|
||||||
|
|
||||||
Takes two optional arguments, ``date_format`` and ``time_format``, which
|
The ``value`` argument used when rendering can be one of two things:
|
||||||
work just like the ``format`` argument for ``DateInput`` and ``TimeInput``.
|
|
||||||
|
|
||||||
.. currentmodule:: django.forms.extras.widgets
|
* A ``list``.
|
||||||
|
* A single value (e.g., a string) that is the "compressed" representation
|
||||||
|
of a ``list`` of values.
|
||||||
|
|
||||||
.. class:: SelectDateWidget
|
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
|
||||||
Wrapper around three select widgets: one each for month, day, and year.
|
does so by calling the ``decompress()`` method, which
|
||||||
Note that this widget lives in a separate file from the standard widgets.
|
:class:`MultiWidget`'s subclasses must implement. This method takes a
|
||||||
|
single "compressed" value and returns a ``list``. An example of this is how
|
||||||
Takes one optional argument:
|
:class:`SplitDateTimeWidget` turns a :class:`datetime` value into a list
|
||||||
|
with date and time split into two seperate values:
|
||||||
.. attribute:: List.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.
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from django.forms.extras.widgets import SelectDateWidget
|
class SplitDateTimeWidget(MultiWidget):
|
||||||
|
|
||||||
date = forms.DateField(widget=SelectDateWidget())
|
# ...
|
||||||
|
|
||||||
Specifying widgets
|
def decompress(self, value):
|
||||||
------------------
|
if value:
|
||||||
.. currentmodule:: django.forms
|
return [value.date(), value.time().replace(microsecond=0)]
|
||||||
|
return [None, None]
|
||||||
|
|
||||||
.. attribute:: Form.widget
|
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.
|
||||||
|
|
||||||
Whenever you specify a field on a form, Django will use a default widget
|
:class:`MultiWidget` has one required argument:
|
||||||
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 for the
|
|
||||||
built-in Field classes.
|
|
||||||
|
|
||||||
However, if you want to use a different widget for a field, you can -
|
.. attribute:: MultiWidget.widgets
|
||||||
just use the 'widget' argument on the field definition. For example::
|
|
||||||
|
|
||||||
from django import forms
|
An iterable containing the widgets needed.
|
||||||
|
|
||||||
class CommentForm(forms.Form):
|
.. class:: SplitDateTimeWidget
|
||||||
name = forms.CharField()
|
|
||||||
url = forms.URLField()
|
|
||||||
comment = forms.CharField(widget=forms.Textarea)
|
|
||||||
|
|
||||||
This would specify a form with a comment that uses a larger Textarea widget,
|
Wrapper (using :class:`MultiWidget`) around two widgets: :class:`DateInput`
|
||||||
rather than the default TextInput widget.
|
for the date, and :class:`TimeInput` for the time.
|
||||||
|
|
||||||
Customizing widget instances
|
``SplitDateTimeWidget`` has two optional attributes:
|
||||||
----------------------------
|
|
||||||
|
|
||||||
When Django renders a widget as HTML, it only renders the bare minimum
|
.. attribute:: SplitDateTimeWidget.date_format
|
||||||
HTML - Django doesn't add a class definition, or any other widget-specific
|
|
||||||
attributes. This means that all 'TextInput' widgets will appear the same
|
|
||||||
on your Web page.
|
|
||||||
|
|
||||||
If you want to make one widget look different to another, you need to
|
Similar to :attr:`DateInput.format`
|
||||||
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::
|
.. attribute:: SplitDateTimeWidget.time_format
|
||||||
|
|
||||||
class CommentForm(forms.Form):
|
Similar to :attr:`TimeInput.format`
|
||||||
name = forms.CharField()
|
|
||||||
url = forms.URLField()
|
|
||||||
comment = forms.CharField()
|
|
||||||
|
|
||||||
This form will include three default 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
|
.. class:: SplitHiddenDateTimeWidget
|
||||||
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 ``attrs``
|
|
||||||
argument when creating the widget:
|
|
||||||
|
|
||||||
.. attribute:: Widget.attrs
|
Similar to :class:`SplitDateTimeWidget`, but uses :class:`HiddenInput` for
|
||||||
|
both date and time.
|
||||||
|
|
||||||
For example::
|
.. currentmodule:: django.forms.widgets.extras
|
||||||
|
|
||||||
class CommentForm(forms.Form):
|
.. class:: SelectDateWidget
|
||||||
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::
|
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.
|
||||||
|
|
||||||
>>> f = CommentForm(auto_id=False)
|
Takes one optional argument:
|
||||||
>>> f.as_table()
|
|
||||||
<tr><th>Name:</th><td><input type="text" name="name" class="special"/></td></tr>
|
.. attribute:: SelectDateWidget.years
|
||||||
<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>
|
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.
|
||||||
|
|
Loading…
Reference in New Issue