Index: django/forms/forms.py
===================================================================
--- django/forms/forms.py	(revision 14551)
+++ django/forms/forms.py	(working copy)
@@ -135,6 +135,19 @@
         """
         return u'initial-%s' % self.add_prefix(field_name)
 
+    def get_field_css_classes(self, bf, css_classes):
+        """
+        Returns the bound field's css classes as set() of strings. Called for
+        each bounded field (parameter *bf*). Parameter *css_classes* holds
+        current field's set of css classes. 
+
+        Subclasses may wish to override.
+
+        See also form class attributes *error_css_class* and
+        *required_css_class*.
+        """
+        return css_classes
+
     def _html_output(self, normal_row, error_row, row_ender, help_text_html, errors_on_separate_row):
         "Helper function for outputting HTML. Used by as_table(), as_ul(), as_p()."
         top_errors = self.non_field_errors() # Errors that should be displayed above all fields.
@@ -497,6 +510,7 @@
             extra_classes.add(self.form.error_css_class)
         if self.field.required and hasattr(self.form, 'required_css_class'):
             extra_classes.add(self.form.required_css_class)
+        extra_classes = self.form.get_field_css_classes(self, extra_classes)
         return ' '.join(extra_classes)
 
     def _is_hidden(self):
Index: tests/regressiontests/forms/forms.py
===================================================================
--- tests/regressiontests/forms/forms.py	(revision 14551)
+++ tests/regressiontests/forms/forms.py	(working copy)
@@ -1885,8 +1885,32 @@
 <tr><th><label for="id_email">Email:</label></th><td><input type="text" name="email" id="id_email" /></td></tr>
 <tr class="required error"><th><label for="id_age">Age:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="age" id="id_age" /></td></tr>
 
+# Check setting custom field css classes by overriding Form.get_field_css_classes function
 
+>>> class Person(Form):
+...     error_css_class = 'error'
+...     required_css_class = 'required'
+...
+...     name = CharField()
+...     is_cool = BooleanField()
+...     age = IntegerField(required=False)
+...
+...     def get_field_css_classes(self, bf, css_classes):
+...         if "required" not in css_classes:
+...             css_classes.add("not_required")
+...         if "error" not in css_classes:
+...             css_classes.add("not_error")
+...         css_classes.add("django-%s" % bf.field.__class__.__name__.lower())
+...         return css_classes
 
+>>> p = Person({"name":"Joe"})
+>>> p.is_valid()
+False
+>>> print p.as_ul()
+<li class="required not_error django-charfield"><label for="id_name">Name:</label> <input type="text" name="name" value="Joe" id="id_name" /></li>
+<li class="django-booleanfield required error"><ul class="errorlist"><li>This field is required.</li></ul><label for="id_is_cool">Is cool:</label> <input type="checkbox" name="is_cool" id="id_is_cool" /></li>
+<li class="django-integerfield not_required not_error"><label for="id_age">Age:</label> <input type="text" name="age" id="id_age" /></li>
+
 # Checking that the label for SplitDateTimeField is not being displayed #####
 
 >>> class EventForm(Form):
Index: docs/ref/forms/api.txt
===================================================================
--- docs/ref/forms/api.txt	(revision 14551)
+++ docs/ref/forms/api.txt	(working copy)
@@ -386,26 +386,39 @@
 errors. For example, you might want to present required form rows in bold and
 highlight errors in red.
 
+``get_field_css_classes()``, ``error_css_class`` and ``required_css_class``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. method:: Form.get_field_css_classes
+
 The :class:`Form` class has a couple of hooks you can use to add ``class``
 attributes to required rows or to rows with errors: simple set the
 :attr:`Form.error_css_class` and/or :attr:`Form.required_css_class`
-attributes::
+attributes and/or override ``get_field_css_classes()`` method ::
 
     class ContactForm(Form):
         error_css_class = 'error'
         required_css_class = 'required'
 
+        def get_field_css_classes(self, bf, css_classes):
+            if "required" not in css_classes:
+                css_classes.add("not_required")
+            if "error" not in css_classes:
+                css_classes.add("not_error")
+            css_classes.add("django-%s" % bf.field.__class__.__name__.lower())
+            return css_classes
+
         # ... and the rest of your fields here
 
-Once you've done that, rows will be given ``"error"`` and/or ``"required"``
-classes, as needed. The HTML will look something like::
+Once you've done that, rows will be given various classes as defined by
+mentioned attributes and method. The HTML will look something like::
 
     >>> f = ContactForm(data)
     >>> print f.as_table()
-    <tr class="required"><th><label for="id_subject">Subject:</label>    ...
-    <tr class="required"><th><label for="id_message">Message:</label>    ...
-    <tr class="required error"><th><label for="id_sender">Sender:</label>      ...
-    <tr><th><label for="id_cc_myself">Cc myself:<label> ...
+    <tr class="django-charfield required not_error"><th><label for="id_subject">Subject:</label>    ...
+    <tr class="django-charfield required not_error"><th><label for="id_message">Message:</label>    ...
+    <tr class="django-emailfield required error"><th><label for="id_sender">Sender:</label>      ...
+    <tr class="django-booleanfield not_required not_error"><th><label for="id_cc_myself">Cc myself:</label> ...
 
 .. _ref-forms-api-configuring-label:
 
