diff -r 41ee28cb9212 docs/ref/forms/fields.txt
--- a/docs/ref/forms/fields.txt	Wed Jun 15 23:52:44 2011 +0000
+++ b/docs/ref/forms/fields.txt	Thu Jun 16 10:11:43 2011 +0200
@@ -278,6 +278,7 @@
 See the :ref:`format localization <format-localization>` documentation for
 more information.
 
+.. _built-in fields:
 
 Built-in ``Field`` classes
 --------------------------
diff -r 41ee28cb9212 docs/ref/forms/widgets.txt
--- a/docs/ref/forms/widgets.txt	Wed Jun 15 23:52:44 2011 +0000
+++ b/docs/ref/forms/widgets.txt	Thu Jun 16 10:11:43 2011 +0200
@@ -11,9 +11,174 @@
 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:
+
+    .. 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 Textarea widget,
+rather than the default TextInput widget.
+
+
+Setting arguments for widgets
+-----------------------------
+
+Many widgets have optional extra arguments; they can be set when defining the
+widget on the field. In this example, the :attr:`~SelectDateWidget.years` 
+attribute is set for a :class:`~django.forms.widgets.extras.SelectDateWidget`:
+
+    .. code-block:: python
+
+        from django import forms
+        from django.forms.widgets.extras import SelectDateWidget
+
+        YEAR_CHOICES = ('2010', '2009',)
+        RADIO_CHOICES = (('1','Radio 1',), ('2','Radio 2',),)
+        CHECKBOX_CHOICES = (('1','The first choice',), ('2','The Second Choice',),)
+
+        class SimpleForm(forms.Form):
+            year = forms.DateField(widget=SelectDateWidget(years=YEAR_CHOICES))
+            radio = forms.ChoiceField(widget=forms.RadioSelect, choices=RADIO_CHOICES)
+            checkboxes = forms.MultipleChoiceField(required=False, 
+                widget=forms.CheckboxSelectMultiple, choices=CHECKBOX_CHOICES)
+
+The section :ref:`built-in widgets` contains 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 '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 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
 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
 
     Text input: ``<input type='text' ...>``
@@ -29,10 +194,10 @@
         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``
+        .. versionchanged:: 1.3
+            The default value for
+            :attr:`~PasswordInput.render_value` was
+            changed from ``True`` to ``False``
 
 .. class:: HiddenInput
 
@@ -42,6 +207,14 @@
 
     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
 
     File upload input: ``<input type='file' ...>``
@@ -64,7 +237,9 @@
 
         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
 
@@ -76,8 +251,9 @@
 
         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
-    %H:%M:%S'``.
+    If no ``format`` argument is provided, the default format is the first 
+    format found in :setting:`DATETIME_INPUT_FORMATS` and respects
+    :ref:`format-localization`.
 
 .. class:: TimeInput
 
@@ -89,7 +265,9 @@
 
         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
 
@@ -111,7 +289,11 @@
 
     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
 
@@ -119,14 +301,12 @@
 
 .. class:: SelectMultiple
 
-    Select widget allowing multiple selection: ``<select
-    multiple='multiple'>...</select>``
-
-    Requires that your field provides :attr:`~Field.choices`.
+    Similar to :class:`Select`, but allows multiple selection:
+    ``<select multiple='multiple'>...</select>``
 
 .. class:: RadioSelect
 
-    A list of radio buttons:
+    Similar to :class:`Select`, but rendered as a list of radio buttons:
 
     .. code-block:: html
 
@@ -135,11 +315,9 @@
           ...
         </ul>
 
-    Requires that your field provides :attr:`~Field.choices`.
-
 .. class:: CheckboxSelectMultiple
 
-    A list of checkboxes:
+    Similar to :class:`SelectMultiple`, but rendered as a list of check buttons:
 
     .. code-block:: html
 
@@ -150,111 +328,82 @@
 
 .. class:: MultiWidget
 
-    Wrapper around multiple other widgets
+    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 normal value (e.g., a string) that has been "compressed" from
+      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` 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:
+
+    .. code-block:: python
+
+        class SplitDateTimeWidget(MultiWidget):
+
+            # ...
+
+            def decompress(self, value):
+                if value:
+                    return [value.date(), value.time().replace(microsecond=0)]
+                return [None, None]
+
+    When ``render`` does 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.
 
 .. class:: SplitDateTimeWidget
 
-    Wrapper around two widgets: ``DateInput`` for the date, and ``TimeInput``
-    for the time.
+    Wrapper (using :class:`MultiWidget`) around two widgets: :class:`DateInput` 
+    for the date, and :class:`TimeInput` for the time.
 
-    Takes two optional arguments, ``date_format`` and ``time_format``, which
-    work just like the ``format`` argument for ``DateInput`` and ``TimeInput``.
+    ``SplitDateTimeWidget`` has two optional attributes:
 
-.. currentmodule:: django.forms.extras.widgets
+    .. attribute:: SplitDateTimeWidget.date_format
+
+        Similar to :attr:`DateInput.format`
+
+    .. attribute:: SplitDateTimeWidget.time_format
+
+        Similar to :attr:`TimeInput.format`
+
+
+.. class:: SplitHiddenDateTimeWidget
+
+    Similar to :class:`SplitDateTimeWidget`, but uses :class:`HiddenInput` for
+    both date and time.
+
+.. currentmodule:: django.forms.widgets.extras
 
 .. class:: SelectDateWidget
 
-    Wrapper around three select widgets: one each for month, day, and year.
+    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:: List.years
+    .. 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.
-
-    .. code-block:: python
-
-        from django.forms.extras.widgets import SelectDateWidget
-
-        date = forms.DateField(widget=SelectDateWidget())
-
-Specifying widgets
-------------------
-.. currentmodule:: django.forms
-
-.. attribute:: Form.widget
-
-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 for the
-built-in Field classes.
-
-However, if you want to use a different widget for a field, you can -
-just use the '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 Textarea widget,
-rather than the default TextInput 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 '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::
-
-    class CommentForm(forms.Form):
-        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
-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
-
-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>
