=== modified file 'django/forms/forms.py'
--- django/forms/forms.py	2008-08-25 11:54:40 +0000
+++ django/forms/forms.py	2008-08-01 09:07:13 +0000
@@ -3,10 +3,12 @@
 """
 
 from copy import deepcopy
+import re
 
 from django.utils.html import conditional_escape
 from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode
 from django.utils.safestring import mark_safe
+from django.utils.text import capfirst
 
 from fields import FileField
 from widgets import Media, TextInput, Textarea
@@ -24,9 +26,22 @@
 
 class FormOptions(object):
     def __init__(self, options=None):
+        # main options
         self.fieldsets = getattr(options, 'fieldsets', None)
         self.fields = getattr(options, 'fields', None)
         self.exclude = getattr(options, 'exclude', None)
+        # other options
+        self.error_class = getattr(options, 'error_class', ErrorList)
+        self.error_row_class = getattr(options, 'error_row_class', 'error')
+        # self.error_row_class = getattr(options, 'error_row_class', None) # backward-compatible
+        self.hidden_row_class = getattr(options, 'hidden_row_class', 'hidden')
+        self.label_capfirst = getattr(options, 'label_capfirst', True)
+        # self.label_capfirst = getattr(options, 'label_capfirst', False) # backward-compatible
+        self.label_suffix = getattr(options, 'label_suffix', ':')
+        self.required_row_class = getattr(options, 'required_row_class', 'required')
+        # self.required_row_class = getattr(options, 'required_row_class', None) # backward-compatible
+        self.use_field_row_class = getattr(options, 'use_field_row_class', True)
+        # self.use_field_row_class = getattr(options, 'use_field_row_class', False) # backward-compatible
 
 class FormMetaclass(type):
     def __new__(cls, name, bases, attrs):
@@ -44,7 +59,7 @@
     # information. Any improvements to the form API should be made to *this*
     # class, not to the Form class.
     def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
-                 initial=None, error_class=ErrorList, label_suffix=':',
+                 initial=None, error_class=None, label_suffix=None,
                  empty_permitted=False):
         self.is_bound = data is not None or files is not None
         self.data = data or {}
@@ -52,8 +67,13 @@
         self.auto_id = auto_id
         self.prefix = prefix
         self.initial = initial or {}
-        self.error_class = error_class
-        self.label_suffix = label_suffix
+        if not hasattr(self, '_meta'):
+            self._options = FormOptions
+            metaclassing.create_meta(self, {})
+        if error_class is not None:
+            self.error_class = error_class
+        if label_suffix is not None:
+            self.label_suffix = label_suffix
         self.empty_permitted = empty_permitted
         self._errors = None # Stores the errors after clean() has been called.
         self._changed_data = None
@@ -152,6 +172,11 @@
             'help_text': self._help_text_html_output(bf, help_text_html),
             'attrs': bf.row_attrs,
         }
+    
+    _field_row_class_re = re.compile(r'([a-z])([A-Z])')
+    def _field_row_class(self, field):
+        return (self._field_row_class_re.sub(r'\1-\2', field.__class__.__name__).lower() +
+            ' ' + self._field_row_class_re.sub(r'\1-\2', field.widget.__class__.__name__).lower())
 
     def _top_errors_html_output(self, top_errors, top_errors_html):
         "Helper function for outputting HTML from a top errors. Used by _html_output."
@@ -182,7 +207,12 @@
 
     def _hidden_fields_html_output(self, hidden_fields, hidden_fields_html):
         "Helper function for outputting HTML from a hidden fields. Used by _html_output."
+        if self.hidden_row_class:
+            attrs = u' class="%s"' % self.hidden_row_class
+        else:
+            attrs = u''
         return hidden_fields_html % {
+            'attrs': attrs,
             'hidden_fields': u''.join(hidden_fields),
         }
 
@@ -226,7 +256,7 @@
             'fieldset_start_html': u'<fieldset%(attrs)s>\n%(legend_tag)s<table>',
             'fieldset_end_html': u'</table>\n</fieldset>',
             'legend_tag_html': u'<legend>%(legend)s</legend>\n',
-            'hidden_fields_html': u'<tr class="hidden"><td colspan="2">%(hidden_fields)s</td></tr>',
+            'hidden_fields_html': u'<tr%(attrs)s><td colspan="2">%(hidden_fields)s</td></tr>',
         }
         return self._html_output(**kwargs)
 
@@ -240,7 +270,7 @@
             'fieldset_start_html': u'<fieldset%(attrs)s>\n%(legend_tag)s<ul>',
             'fieldset_end_html': u'</ul>\n</fieldset>',
             'legend_tag_html': u'<legend>%(legend)s</legend>\n',
-            'hidden_fields_html': u'<li class="hidden">%(hidden_fields)s</li>',
+            'hidden_fields_html': u'<li%(attrs)s>%(hidden_fields)s</li>',
         }
         return self._html_output(**kwargs)
 
@@ -254,7 +284,7 @@
             'fieldset_start_html': u'<fieldset%(attrs)s>\n%(legend_tag)s',
             'fieldset_end_html': u'</fieldset>',
             'legend_tag_html': u'<legend>%(legend)s</legend>\n',
-            'hidden_fields_html': u'<p class="hidden">%(hidden_fields)s</p>',
+            'hidden_fields_html': u'<p%(attrs)s>%(hidden_fields)s</p>',
         }
         return self._html_output(**kwargs)
 
@@ -439,7 +469,10 @@
         if self.field.label is None:
             return pretty_name(self.name)
         else:
-            return conditional_escape(force_unicode(self.field.label))
+            label = conditional_escape(force_unicode(self.field.label))
+            if self.form.label_capfirst:
+                label = capfirst(label)
+            return label
     label = property(_label)
 
     def _label_id(self):
@@ -459,7 +492,17 @@
 
     def _row_attrs(self):
         "Returns row attributes for this field as safe HTML."
-        return flatatt(self.widget.row_attrs)
+        attrs = self.widget.row_attrs.copy()
+        class_list = attrs.pop('class', '').split()
+        if self.form.error_row_class and self.errors:
+            class_list.append(self.form.error_row_class)
+        if self.form.required_row_class and self.required:
+            class_list.append(self.form.required_row_class)
+        if self.form.use_field_row_class:
+            class_list.append(self.form._field_row_class(self.field))
+        if class_list:
+            attrs['class'] = u' '.join(class_list)
+        return flatatt(attrs)
     row_attrs = property(_row_attrs)
 
     def label_tag(self, contents=None, attrs=None):

=== modified file 'django/forms/metaclassing.py'
--- django/forms/metaclassing.py	2008-08-01 08:58:33 +0000
+++ django/forms/metaclassing.py	2008-08-01 08:59:48 +0000
@@ -10,6 +10,9 @@
 
 def create_meta(cls, attrs):
     cls._meta = cls._options(getattr(cls, 'Meta', None))
+    for name, attr in cls._meta.__dict__.items():
+        if name not in ('fieldsets', 'fields', 'exclude'):
+            setattr(cls, name, attr)
 
 def create_declared_fields(cls, attrs):
     fields = []
@@ -23,8 +26,8 @@
 def create_model_fields(cls, attrs):
     formfield_callback = attrs.pop('formfield_callback', lambda f: f.formfield())
     fields = []
-    if cls._meta.model:
-        for dbfield in cls._meta.model._meta.fields + cls._meta.model._meta.many_to_many:
+    if cls.model:
+        for dbfield in cls.model._meta.fields + cls.model._meta.many_to_many:
             if dbfield.editable:
                 formfield = formfield_callback(dbfield)
                 if formfield:
@@ -45,7 +48,7 @@
     for base in cls.__mro__[::-1]:
         try:
             declared_fields += base.declared_fields.items()
-            if base._meta.model:
+            if base.model:
                 model_fields = base.model_fields.items()
         except AttributeError:
             pass

=== modified file 'django/forms/models.py'
--- django/forms/models.py	2008-08-30 11:00:58 +0000
+++ django/forms/models.py	2008-08-30 11:01:36 +0000
@@ -7,7 +7,7 @@
 from django.utils.encoding import smart_unicode
 from django.utils.datastructures import SortedDict
 
-from util import ValidationError, ErrorList
+from util import ValidationError
 from forms import FormOptions, FormMetaclass, BaseForm
 from fields import Field, ChoiceField, IntegerField, EMPTY_VALUES
 from widgets import Select, SelectMultiple, HiddenInput, MultipleHiddenInput
@@ -165,7 +165,7 @@
 
 class BaseModelForm(BaseForm):
     def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
-                 initial=None, error_class=ErrorList, label_suffix=':',
+                 initial=None, error_class=None, label_suffix=None,
                  empty_permitted=False, instance=None):
         opts = self._meta
         if instance is None:

