mirror of https://github.com/django/django.git
Fixed #11185 - Expanded docs on customizing widgets; thanks fadeev for the draft patch.
This commit is contained in:
parent
65793d714c
commit
a73838fde3
|
@ -852,7 +852,7 @@ Slightly complex built-in ``Field`` classes
|
||||||
``MultiValueField``
|
``MultiValueField``
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. class:: MultiValueField(**kwargs)
|
.. class:: MultiValueField(fields=(), **kwargs)
|
||||||
|
|
||||||
* Default widget: ``TextInput``
|
* Default widget: ``TextInput``
|
||||||
* Empty value: ``''`` (an empty string)
|
* Empty value: ``''`` (an empty string)
|
||||||
|
@ -861,22 +861,39 @@ Slightly complex built-in ``Field`` classes
|
||||||
as an argument to the ``MultiValueField``.
|
as an argument to the ``MultiValueField``.
|
||||||
* Error message keys: ``required``, ``invalid``
|
* Error message keys: ``required``, ``invalid``
|
||||||
|
|
||||||
This abstract field (must be subclassed) aggregates the logic of multiple
|
Aggregates the logic of multiple fields that together produce a single
|
||||||
fields. Subclasses should not have to implement clean(). Instead, they must
|
value.
|
||||||
implement compress(), which takes a list of valid values and returns a
|
|
||||||
"compressed" version of those values -- a single value. For example,
|
This field is abstract and must be subclassed. In contrast with the
|
||||||
:class:`SplitDateTimeField` is a subclass which combines a time field and
|
single-value fields, subclasses of :class:`MultiValueField` must not
|
||||||
a date field into a datetime object.
|
implement :meth:`~django.forms.Field.clean` but instead - implement
|
||||||
|
:meth:`~MultiValueField.compress`.
|
||||||
|
|
||||||
Takes one extra required argument:
|
Takes one extra required argument:
|
||||||
|
|
||||||
.. attribute:: fields
|
.. attribute:: fields
|
||||||
|
|
||||||
A list of fields which are cleaned into a single field. Each value in
|
A tuple of fields whose values are cleaned and subsequently combined
|
||||||
``clean`` is cleaned by the corresponding field in ``fields`` -- the first
|
into a single value. Each value of the field is cleaned by the
|
||||||
value is cleaned by the first field, the second value is cleaned by
|
corresponding field in ``fields`` -- the first value is cleaned by the
|
||||||
the second field, etc. Once all fields are cleaned, the list of clean
|
first field, the second value is cleaned by the second field, etc.
|
||||||
values is "compressed" into a single value.
|
Once all fields are cleaned, the list of clean values is combined into
|
||||||
|
a single value by :meth:`~MultiValueField.compress`.
|
||||||
|
|
||||||
|
.. attribute:: MultiValueField.widget
|
||||||
|
|
||||||
|
Must be a subclass of :class:`django.forms.MultiWidget`.
|
||||||
|
Default value is :class:`~django.forms.widgets.TextInput`, which
|
||||||
|
probably is not very useful in this case.
|
||||||
|
|
||||||
|
.. method:: compress(data_list)
|
||||||
|
|
||||||
|
Takes a list of valid values and returns a "compressed" version of
|
||||||
|
those values -- in a single value. For example,
|
||||||
|
:class:`SplitDateTimeField` is a subclass which combines a time field
|
||||||
|
and a date field into a ``datetime`` object.
|
||||||
|
|
||||||
|
This method must be implemented in the subclasses.
|
||||||
|
|
||||||
``SplitDateTimeField``
|
``SplitDateTimeField``
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
@ -11,6 +11,16 @@ 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.
|
||||||
|
|
||||||
|
.. 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
|
Specifying widgets
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
@ -95,15 +105,23 @@ choices are inherent to the model and not just the representational widget.
|
||||||
Customizing widget instances
|
Customizing widget instances
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
When Django renders a widget as HTML, it only renders the bare minimum
|
When Django renders a widget as HTML, it only renders very minimal markup -
|
||||||
HTML - Django doesn't add a class definition, or any other widget-specific
|
Django doesn't add class names, or any other widget-specific attributes. This
|
||||||
attributes. This means that all :class:`TextInput` widgets will appear the same
|
means, for example, that all :class:`TextInput` widgets will appear the same
|
||||||
on your Web page.
|
on your Web pages.
|
||||||
|
|
||||||
If you want to make one widget look different to another, you need to
|
There are two ways to customize widgets: :ref:`per widget instance
|
||||||
specify additional attributes for each widget. When you specify a
|
<styling-widget-instances>` and :ref:`per widget class <styling-widget-classes>`.
|
||||||
widget, you can provide a list of attributes that will be added to the
|
|
||||||
rendered HTML for the widget.
|
.. _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::
|
For example, take the following simple form::
|
||||||
|
|
||||||
|
@ -128,9 +146,7 @@ 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
|
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
|
'name' widget to have some special CSS class. It is also possible to specify
|
||||||
the 'type' attribute to take advantage of the new HTML5 input types. To do
|
the 'type' attribute to take advantage of the new HTML5 input types. To do
|
||||||
this, you use the :attr:`Widget.attrs` argument when creating the widget:
|
this, you use the :attr:`Widget.attrs` argument when creating the widget::
|
||||||
|
|
||||||
For example::
|
|
||||||
|
|
||||||
class CommentForm(forms.Form):
|
class CommentForm(forms.Form):
|
||||||
name = forms.CharField(
|
name = forms.CharField(
|
||||||
|
@ -147,24 +163,41 @@ Django will then include the extra attributes in the rendered output:
|
||||||
<tr><th>Url:</th><td><input type="text" name="url"/></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>
|
<tr><th>Comment:</th><td><input type="text" name="comment" size="40"/></td></tr>
|
||||||
|
|
||||||
.. _built-in widgets:
|
.. _styling-widget-classes:
|
||||||
|
|
||||||
Built-in widgets
|
Styling widget classes
|
||||||
----------------
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Django provides a representation of all the basic HTML widgets, plus some
|
With widgets, it is possible to add media (``css`` and ``javascript``)
|
||||||
commonly used groups of widgets:
|
and more deeply customize their appearance and behavior.
|
||||||
|
|
||||||
``Widget``
|
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.
|
||||||
|
|
||||||
.. class:: Widget
|
These methods involve somewhat advanced Python programming and are described in
|
||||||
|
detail in the :doc:`Form Media </topics/forms/media>` topic guide.
|
||||||
|
|
||||||
This abstract class cannot be rendered, but provides the basic attribute :attr:`~Widget.attrs`.
|
.. _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
|
.. attribute:: Widget.attrs
|
||||||
|
|
||||||
A dictionary containing HTML attributes to be set on the rendered widget.
|
A dictionary containing HTML attributes to be set on the rendered
|
||||||
|
widget.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -172,6 +205,74 @@ commonly used groups of widgets:
|
||||||
>>> name.render('name', 'A name')
|
>>> name.render('name', 'A name')
|
||||||
u'<input title="Your name" type="text" name="name" value="A name" size="10" />'
|
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.
|
||||||
|
|
||||||
|
.. 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`.
|
||||||
|
|
||||||
|
.. method:: render(name, value, attrs=None)
|
||||||
|
|
||||||
|
Argument `value` is handled differently in this method from the
|
||||||
|
subclasses of :class:`~Widget`.
|
||||||
|
|
||||||
|
If `value` is a list, output of :meth:`~MultiWidget.render` will be a
|
||||||
|
concatenation of rendered child widgets. If `value` is not a list, it
|
||||||
|
will be first processed by the method :meth:`~MultiWidget.decompress()`
|
||||||
|
to create the list and then processed as above.
|
||||||
|
|
||||||
|
Unlike in the single value widgets, method :meth:`~MultiWidget.render`
|
||||||
|
need not be implemented in the subclasses.
|
||||||
|
|
||||||
|
.. method:: decompress(value)
|
||||||
|
|
||||||
|
Returns a list of "decompressed" values for the given value of the
|
||||||
|
multi-value field that makes use of the widget. The input value can be
|
||||||
|
assumed as 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 of the individual
|
||||||
|
field encapsulated within the multi-value field (e.g. when displaying
|
||||||
|
the partially or fully filled-out form).
|
||||||
|
|
||||||
|
.. 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.
|
||||||
|
|
||||||
|
|
||||||
|
.. _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``
|
``TextInput``
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -205,39 +306,8 @@ commonly used groups of widgets:
|
||||||
|
|
||||||
Hidden input: ``<input type='hidden' ...>``
|
Hidden input: ``<input type='hidden' ...>``
|
||||||
|
|
||||||
``MultipleHiddenInput``
|
Note that there also is a :class:`MultipleHiddenInput` widget that
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
encapsulates a set of hidden input elements.
|
||||||
|
|
||||||
.. 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``
|
``DateInput``
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
@ -297,6 +367,11 @@ commonly used groups of widgets:
|
||||||
|
|
||||||
Text area: ``<textarea>...</textarea>``
|
Text area: ``<textarea>...</textarea>``
|
||||||
|
|
||||||
|
.. _selector-widgets:
|
||||||
|
|
||||||
|
Selector and checkbox widgets
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
``CheckboxInput``
|
``CheckboxInput``
|
||||||
~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -440,6 +515,50 @@ commonly used groups of widgets:
|
||||||
...
|
...
|
||||||
</ul>
|
</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`.
|
||||||
|
|
||||||
``MultiWidget``
|
``MultiWidget``
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,8 @@ in a form suitable for easy inclusion on your Web page.
|
||||||
whichever toolkit suits your requirements. Django is able to integrate
|
whichever toolkit suits your requirements. Django is able to integrate
|
||||||
with any JavaScript toolkit.
|
with any JavaScript toolkit.
|
||||||
|
|
||||||
|
.. _media-as-a-static-definition:
|
||||||
|
|
||||||
Media as a static definition
|
Media as a static definition
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
@ -78,10 +80,8 @@ A dictionary describing the CSS files required for various forms of output
|
||||||
media.
|
media.
|
||||||
|
|
||||||
The values in the dictionary should be a tuple/list of file names. See
|
The values in the dictionary should be a tuple/list of file names. See
|
||||||
`the section on media paths`_ for details of how to specify paths to media
|
:ref:`the section on media paths <form-media-paths>` for details of how to
|
||||||
files.
|
specify paths to media files.
|
||||||
|
|
||||||
.. _the section on media paths: `Paths in media definitions`_
|
|
||||||
|
|
||||||
The keys in the dictionary are the output media types. These are the same
|
The keys in the dictionary are the output media types. These are the same
|
||||||
types accepted by CSS files in media declarations: 'all', 'aural', 'braille',
|
types accepted by CSS files in media declarations: 'all', 'aural', 'braille',
|
||||||
|
@ -117,8 +117,8 @@ If this last CSS definition were to be rendered, it would become the following H
|
||||||
``js``
|
``js``
|
||||||
~~~~~~
|
~~~~~~
|
||||||
|
|
||||||
A tuple describing the required JavaScript files. See
|
A tuple describing the required JavaScript files. See :ref:`the section on
|
||||||
`the section on media paths`_ for details of how to specify paths to media
|
media paths <form-media-paths>` for details of how to specify paths to media
|
||||||
files.
|
files.
|
||||||
|
|
||||||
``extend``
|
``extend``
|
||||||
|
@ -164,10 +164,10 @@ declaration to the media declaration::
|
||||||
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>
|
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>
|
||||||
|
|
||||||
If you require even more control over media inheritance, define your media
|
If you require even more control over media inheritance, define your media
|
||||||
using a `dynamic property`_. Dynamic properties give you complete control over
|
using a :ref:`dynamic property <dynamic-property>`. Dynamic properties give
|
||||||
which media files are inherited, and which are not.
|
you complete control over which media files are inherited, and which are not.
|
||||||
|
|
||||||
.. _dynamic property: `Media as a dynamic property`_
|
.. _dynamic-property:
|
||||||
|
|
||||||
Media as a dynamic property
|
Media as a dynamic property
|
||||||
---------------------------
|
---------------------------
|
||||||
|
@ -198,9 +198,9 @@ Paths in media definitions
|
||||||
.. versionchanged:: 1.3
|
.. versionchanged:: 1.3
|
||||||
|
|
||||||
Paths used to specify media can be either relative or absolute. If a path
|
Paths used to specify media can be either relative or absolute. If a path
|
||||||
starts with '/', 'http://' or 'https://', it will be interpreted as an absolute
|
starts with ``/``, ``http://`` or ``https://``, it will be interpreted as an
|
||||||
path, and left as-is. All other paths will be prepended with the value of
|
absolute path, and left as-is. All other paths will be prepended with the value
|
||||||
the appropriate prefix.
|
of the appropriate prefix.
|
||||||
|
|
||||||
As part of the introduction of the
|
As part of the introduction of the
|
||||||
:doc:`staticfiles app </ref/contrib/staticfiles>` two new settings were added
|
:doc:`staticfiles app </ref/contrib/staticfiles>` two new settings were added
|
||||||
|
|
Loading…
Reference in New Issue