diff --git a/django/forms/widgets.py b/django/forms/widgets.py
index dd5868f..701fa79 100644
--- a/django/forms/widgets.py
+++ b/django/forms/widgets.py
@@ -136,6 +136,8 @@ class MediaDefiningClass(type):
         return new_class
 
 class Widget(object):
+    """Base class for all :ref:`built-in widgets <builtin-widgets>`
+    """
     __metaclass__ = MediaDefiningClass
     is_hidden = False          # Determines whether this corresponds to an <input type="hidden">.
     needs_multipart_form = False # Determines does this widget need multipart-encrypted form
@@ -156,10 +158,10 @@ class Widget(object):
 
     def render(self, name, value, attrs=None):
         """
-        Returns this Widget rendered as HTML, as a Unicode string.
+        Returns HTML for the widget, as a Unicode string.
 
-        The 'value' given is not guaranteed to be valid input, so subclass
-        implementations should program defensively.
+        The 'value' given is not guaranteed to be valid input,
+        therefore subclass implementations should program defensively.
         """
         raise NotImplementedError
 
diff --git a/docs/index.txt b/docs/index.txt
index 0cf066e..ee7ab15 100644
--- a/docs/index.txt
+++ b/docs/index.txt
@@ -124,7 +124,7 @@ Forms
       :doc:`Overview <topics/forms/index>` |
       :doc:`Form API <ref/forms/api>` |
       :doc:`Built-in fields <ref/forms/fields>` |
-      :doc:`Built-in widgets <ref/forms/widgets>`
+      :doc:`Widgets <ref/forms/widgets>`
 
     * **Advanced:**
       :doc:`Forms for models <topics/forms/modelforms>` |
diff --git a/docs/ref/forms/fields.txt b/docs/ref/forms/fields.txt
index b49864f..20ba4c7 100644
--- a/docs/ref/forms/fields.txt
+++ b/docs/ref/forms/fields.txt
@@ -278,6 +278,7 @@ as the rendered output.
 See the :ref:`format localization <format-localization>` documentation for
 more information.
 
+.. _builtin-form-fields:
 
 Built-in ``Field`` classes
 --------------------------
@@ -797,34 +798,57 @@ Takes one extra required argument:
         ...
         ValidationError: [u'Ensure this value has at most 20 characters (it has 28).']
 
+.. _multi-value-field:
+
 ``MultiValueField``
 ~~~~~~~~~~~~~~~~~~~
 
-.. class:: MultiValueField(**kwargs)
+.. class:: MultiValueField(fields = (), **kwargs)
+
+    Aggregates the logic of multiple fields that together
+    produce a single cleaned value.
+
+    This field is abstract and must be subclassed.
+    Also, in contrast with the single-value fields
+    the subclasses of :class:`MultiValueField`
+    must not implement :meth:`~forms.Field.clean`
+    but
+    instead - implement :meth:`~forms.MultiValueField.compress`.
 
-    * Default widget: ``TextInput``
     * Empty value: ``''`` (an empty string)
     * Normalizes to: the type returned by the ``compress`` method of the subclass.
     * Validates that the given value against each of the fields specified
       as an argument to the ``MultiValueField``.
     * Error message keys: ``required``, ``invalid``
 
-    This abstract field (must be subclassed) aggregates the logic of multiple
-    fields. Subclasses should not have to implement clean(). Instead, they must
-    implement compress(), which takes a list of valid values and returns a
-    "compressed" version of those values -- a single value.  For example,
-    :class:`SplitDateTimeField` is a subclass which combines a time field and
-    a date field into a datetime object.
-
-Takes one extra required argument:
-
 .. attribute:: MultiValueField.fields
 
-    A list of fields which are cleaned into a single field. Each value in
-    ``clean`` is cleaned by the corresponding field in ``fields`` -- the first
-    value is cleaned by the first field, the second value is cleaned by
-    the second field, etc.  Once all fields are cleaned, the list of clean
-    values is "compressed" into a single value.
+    A tuple of fields whose values are cleaned
+    and
+    subsequently combined into a single value.
+    More specifically, each value of the field
+    is cleaned by the corresponding field in ``fields``
+    -- the first value is cleaned by the first field,
+    the second value is cleaned by the second field, etc.
+    Once all fields are cleaned,
+    the list of clean values is combined into a single value
+    by the :meth:`~forms.MultiValueField.compress`.
+
+.. attribute:: MultiValueField.widget
+
+    Must be a subclass of 
+    :class:`django.forms.MultiWidget`.
+    Default value is :class:`~forms.widgets.TextInput`,
+    which is 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``
 ~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/ref/forms/widgets.txt b/docs/ref/forms/widgets.txt
index dbdf109..7b452b1 100644
--- a/docs/ref/forms/widgets.txt
+++ b/docs/ref/forms/widgets.txt
@@ -2,17 +2,64 @@
 Widgets
 =======
 
+The term "widget" for the purposes of this document is narrower
+than usually assumed elsewhere.
+
+In Django, widget is a Python object responsible for three things:
+
+#. generation of a subtree of HTML document
+   where users can enter some data
+#. extraction of raw data from the request's GET/POST dictionary
+   entered into the element decribed above
+#. optionally - provide media (e.g. javacript and CSS) for the widget
+
+Objects of widget classes wrap "native HTML widget" elements:
+``input``,
+``textarea``, 
+``select`` and ``option``,
+but in addition they may include other HTML constructs
+and
+may contain more than one "native HTML widget".
+
+.. tip::
+
+    Widgets should not be confused with the :doc:`form fields </ref/forms/fields>`.
+    Form fields concern with the logic of input validation,
+    and are directly used in the templates.
+    Widgets purely deal with 
+    rendering of the data entry for display on the web page
+    and
+    extraction of raw submitted data.
+    
+    However, in order to take effect, widgets do need to be
+    :ref:`assigned <widget-to-field>`
+    to the form fields.
+
+.. _builtin-widgets:
+
+Built-in widgets
+----------------
+
+All built-in widgets are part of the ``django.forms.widgets`` module
+and
+handle many common use cases for
+: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>`.
+
 .. 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.
+.. _text-widgets:
+
+Widgets handling input of text
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-Django provides a representation of all the basic HTML widgets, plus some
-commonly used groups of widgets:
+These widgets make use of the HTML elements `input` and `textarea`.
 
 .. class:: TextInput
 
@@ -30,29 +77,16 @@ commonly used groups of widgets:
         form is re-displayed after a validation error (default is ``False``).
 
 .. versionchanged:: 1.3
-    The default value for
-    :attr:`~PasswordInput.render_value` was
+    The default value for ``render_value`` was
     changed from ``True`` to ``False``
 
 .. class:: HiddenInput
 
     Hidden input: ``<input type='hidden' ...>``
-
-.. class:: MultipleHiddenInput
-
-    Multiple ``<input type='hidden' ...>`` widgets.
-
-.. class:: FileInput
-
-    File upload input: ``<input type='file' ...>``
-
-.. 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.
+    
+    Please note that
+    there also is a :ref:`MultipleHiddenInput <multiple-hidden>` widget
+    that encapsulates a set of hidden input elements.
 
 .. class:: DateInput
 
@@ -95,6 +129,11 @@ commonly used groups of widgets:
 
     Text area: ``<textarea>...</textarea>``
 
+.. _selector-widgets:
+
+Selector and checkbox widgets
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 .. class:: CheckboxInput
 
     Checkbox: ``<input type='checkbox' ...>``
@@ -148,9 +187,28 @@ commonly used groups of widgets:
           ...
         </ul>
 
-.. class:: MultiWidget
+.. _file-upload-widgets:
+
+File upload widgets
+^^^^^^^^^^^^^^^^^^^
+
+.. class:: FileInput
+
+    File upload input: ``<input type='file' ...>``
+
+.. class:: ClearableFileInput
+
+    .. versionadded:: 1.3
 
-    Wrapper around multiple other widgets
+    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
+^^^^^^^^^^^^^^^^^
 
 .. class:: SplitDateTimeWidget
 
@@ -169,7 +227,7 @@ commonly used groups of 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.
@@ -180,19 +238,26 @@ commonly used groups of widgets:
 
         date = forms.DateField(widget=SelectDateWidget())
 
-Specifying widgets
-------------------
-.. currentmodule:: django.forms
+.. _multiple-hidden:
 
-.. attribute:: Form.widget
+.. class:: MultipleHiddenInput
+
+    Multiple ``<input type='hidden' ...>`` widgets.
+
+.. _widget-to-field:
+
+Assigning widgets to form fields
+--------------------------------
+.. currentmodule:: django.forms
 
 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.
+which widget is used on which field,
+see the :ref:`documentation for the built-in Field classes
+<builtin-form-fields>`.
 
 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::
+just use the ``widget`` argument on the field definition. For example::
 
     from django import forms
 
@@ -201,21 +266,37 @@ just use the 'widget' argument on the field definition. For example::
         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.
+This will specify a form with a comment that uses a larger ``Textarea`` widget,
+rather than the default ``TextInput`` widget.
+
+Styling and adding behavior to widgets
+--------------------------------------
+
+When Django renders a widget as HTML,
+it only produces the very minimal markup
+- Django doesn't add class names
+or
+any other widget-specific attributes.
+This means, for example, that
+all instances of ``TextInput`` widget
+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>`.
 
-Customizing widget instances
-----------------------------
+.. _styling-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.
+Styling widget instances
+^^^^^^^^^^^^^^^^^^^^^^^^
 
-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.
+If you want to make one widget instance look different from another,
+all you will need to do is 
+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::
 
@@ -234,15 +315,10 @@ each widget will be rendered exactly the same::
     <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::
+argument when creating the widget::
 
     class CommentForm(forms.Form):
         name = forms.CharField(
@@ -258,3 +334,133 @@ Django will then include the extra attributes in the rendered output::
     <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 customise 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>` tutorial.
+
+.. _base-widget-classes:
+
+Base Widget classes 
+-------------------
+
+Base widget classes
+:class:`~django.forms.widgets.Widget`
+and
+:class:`~django.forms.widgets.MultiWidget`
+are subclassed by
+all the :ref:`built-in widgets <builtin-widgets>`
+and may serve as a foundation for the custom ones
+(but, please see the warning below).
+
+.. warning::
+
+   Interfaces of classes
+   :class:`~django.forms.widgets.Widget`
+   and
+   :class:`~django.forms.widgets.MultiWidget`
+   are still in flux,
+   therefore -
+   please take care to test all of your custom widgets
+   when upgrading django.
+   It is a particularly good idea to create 
+   :doc:`automated test suite </topics/testing>`
+   for any of your custom widgets.
+
+.. currentmodule:: django.forms
+
+.. class:: Widget(attrs=None)
+
+    .. 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 :meth:`~django.forms.widgets.Widget`.
+
+        If `value` is a list, output of
+        :meth:`~django.forms.widgets.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:`~django.forms.widgets.MultiWidget.decompress()`
+        to create the list, and then processed as above.
+
+        Unlike in the single value widgets, 
+        method :meth:`~django.forms.widgets.MultiWidget.render`
+        should not be implemented in the subclasses
+        of :class:`~django.forms.widgets.MultiWidget`.
+
+    .. 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 fields
+        encapsulated within the multi-value field
+        (e.g. when displaying the partially or fully filled-out form).
+
+        .. tip::
+
+            Please, note that :class:`~django.forms.MultiValueField` has
+            a complementary method :meth:`~django.forms.MultiValueField.compress`
+            with the opposite responsibility - combine cleaned values of
+            all memeber fields into one.
+
+.. custom-widgets:
+
+Custom Widgets
+--------------
+
+Those who wish to create their own custom widgets
+can use the APIs of classes
+:class:`~django.forms.widgets.Widget`
+and
+:class:`~django.forms.widgets.MultiWidget`.
+
+However, please do notice that those APIs
+are subject to the future changes.
+
+Since there are two :ref:`widget base classes <base-widget-classes>`,
+two types of custom widgets are possible:
+single-value widgets
+and
+multi-value composite widgets.
+The patterns of their creation are somewhat different.
diff --git a/docs/topics/forms/media.txt b/docs/topics/forms/media.txt
index 0eb3e91..2f6b3ec 100644
--- a/docs/topics/forms/media.txt
+++ b/docs/topics/forms/media.txt
@@ -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
     with any JavaScript toolkit.
 
+.. _media-as-a-static-definition:
+
 Media as a static definition
 ----------------------------
 
@@ -164,10 +166,11 @@ declaration to the media declaration::
     <script type="text/javascript" src="http://media.example.com/whizbang.js"></script>
 
 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>` technique.
+Dynamic properties give 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
 ---------------------------
@@ -198,7 +201,7 @@ Paths in media definitions
 .. versionchanged:: 1.3
 
 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 absolute
 path, and left as-is. All other paths will be prepended with the value of
 the appropriate prefix.
 
