=== modified file 'django/contrib/contenttypes/generic.py'
--- django/contrib/contenttypes/generic.py	2008-08-10 04:03:01 +0000
+++ django/contrib/contenttypes/generic.py	2008-08-26 05:02:24 +0000
@@ -2,18 +2,16 @@
 Classes allowing "generic" relations through ContentType and object-id fields.
 """
 
-from django import oldforms
 from django.core.exceptions import ObjectDoesNotExist
 from django.db import connection
 from django.db.models import signals
 from django.db import models
 from django.db.models.fields.related import RelatedField, Field, ManyToManyRel
 from django.db.models.loading import get_model
-from django.utils.functional import curry
-
 from django.forms import ModelForm
 from django.forms.models import BaseModelFormSet, modelformset_factory, save_instance
 from django.contrib.admin.options import InlineModelAdmin, flatten_fieldsets
+from django.utils.encoding import smart_unicode
 
 class GenericForeignKey(object):
     """
@@ -120,19 +118,12 @@
         kwargs['serialize'] = False
         Field.__init__(self, **kwargs)
 
-    def get_manipulator_field_objs(self):
-        choices = self.get_choices_default()
-        return [curry(oldforms.SelectMultipleField, size=min(max(len(choices), 5), 15), choices=choices)]
-
     def get_choices_default(self):
         return Field.get_choices(self, include_blank=False)
 
-    def flatten_data(self, follow, obj = None):
-        new_data = {}
-        if obj:
-            instance_ids = [instance._get_pk_val() for instance in getattr(obj, self.name).all()]
-            new_data[self.name] = instance_ids
-        return new_data
+    def get_string_value(self, obj):
+        qs = getattr(obj, self.name).all()
+        return smart_unicode([instance._get_pk_val() for instance in qs])
 
     def m2m_db_table(self):
         return self.rel.to._meta.db_table
@@ -290,7 +281,7 @@
     """
     ct_field_name = "content_type"
     ct_fk_field_name = "object_id"
-    
+
     def __init__(self, data=None, files=None, instance=None, save_as_new=None):
         opts = self.model._meta
         self.instance = instance
@@ -385,4 +376,3 @@
 
 class GenericTabularInline(GenericInlineModelAdmin):
     template = 'admin/edit_inline/tabular.html'
-

=== modified file 'django/core/serializers/base.py'
--- django/core/serializers/base.py	2008-07-30 10:40:37 +0000
+++ django/core/serializers/base.py	2008-08-26 05:02:24 +0000
@@ -57,12 +57,7 @@
         """
         Convert a field's value to a string.
         """
-        if isinstance(field, models.DateTimeField):
-            d = datetime_safe.new_datetime(getattr(obj, field.name))
-            value = d.strftime("%Y-%m-%d %H:%M:%S")
-        else:
-            value = field.flatten_data(follow=None, obj=obj).get(field.name, "")
-        return smart_unicode(value)
+        return smart_unicode(field.get_string_value(obj))
 
     def start_serialization(self):
         """

=== modified file 'django/db/models/base.py'
--- django/db/models/base.py	2008-08-14 15:37:43 +0000
+++ django/db/models/base.py	2008-08-26 05:02:24 +0000
@@ -8,8 +8,7 @@
 except NameError:
     from sets import Set as set     # Python 2.3 fallback.
 
-import django.db.models.manipulators    # Imported to register signal handler.
-import django.db.models.manager         # Ditto.
+import django.db.models.manager     # Imported to register signal handler.
 from django.core import validators
 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError
 from django.db.models.fields import AutoField
@@ -320,9 +319,7 @@
 
         # First, try an UPDATE. If that doesn't update anything, do an INSERT.
         pk_val = self._get_pk_val(meta)
-        # Note: the comparison with '' is required for compatibility with
-        # oldforms-style model creation.
-        pk_set = pk_val is not None and smart_unicode(pk_val) != u''
+        pk_set = pk_val is not None
         record_exists = True
         manager = cls._default_manager
         if pk_set:

=== modified file 'django/db/models/fields/__init__.py'
--- django/db/models/fields/__init__.py	2008-08-25 03:51:25 +0000
+++ django/db/models/fields/__init__.py	2008-08-26 05:02:24 +0000
@@ -13,7 +13,6 @@
 from django.dispatch import dispatcher
 from django.conf import settings
 from django.core import validators
-from django import oldforms
 from django import forms
 from django.core.exceptions import ObjectDoesNotExist
 from django.utils.datastructures import DictWrapper
@@ -34,17 +33,6 @@
 class FieldDoesNotExist(Exception):
     pass
 
-def manipulator_validator_unique(f, opts, self, field_data, all_data):
-    "Validates that the value is unique for this field."
-    lookup_type = f.get_validator_unique_lookup_type()
-    try:
-        old_obj = self.manager.get(**{lookup_type: field_data})
-    except ObjectDoesNotExist:
-        return
-    if getattr(self, 'original_object', None) and self.original_object._get_pk_val() == old_obj._get_pk_val():
-        return
-    raise validators.ValidationError, _("%(optname)s with this %(fieldname)s already exists.") % {'optname': capfirst(opts.verbose_name), 'fieldname': f.verbose_name}
-
 # A guide to Field parameters:
 #
 #   * name:      The name of the field specifed in the model.
@@ -75,8 +63,8 @@
             max_length=None, unique=False, blank=False, null=False,
             db_index=False, core=False, rel=None, default=NOT_PROVIDED,
             editable=True, serialize=True, unique_for_date=None,
-            unique_for_month=None, unique_for_year=None, validator_list=None,
-            choices=None, help_text='', db_column=None, db_tablespace=None,
+            unique_for_month=None, unique_for_year=None, choices=None,
+            help_text='', db_column=None, db_tablespace=None,
             auto_created=False):
         self.name = name
         self.verbose_name = verbose_name
@@ -90,7 +78,6 @@
         self.core, self.rel, self.default = core, rel, default
         self.editable = editable
         self.serialize = serialize
-        self.validator_list = validator_list or []
         self.unique_for_date, self.unique_for_month = unique_for_date, unique_for_month
         self.unique_for_year = unique_for_year
         self._choices = choices or []
@@ -252,93 +239,9 @@
             return None
         return ""
 
-    def get_manipulator_field_names(self, name_prefix):
-        """
-        Returns a list of field names that this object adds to the manipulator.
-        """
-        return [name_prefix + self.name]
-
-    def prepare_field_objs_and_params(self, manipulator, name_prefix):
-        params = {'validator_list': self.validator_list[:]}
-        if self.max_length and not self.choices: # Don't give SelectFields a max_length parameter.
-            params['max_length'] = self.max_length
-
-        if self.choices:
-            field_objs = [oldforms.SelectField]
-
-            params['choices'] = self.get_flatchoices()
-        else:
-            field_objs = self.get_manipulator_field_objs()
-        return (field_objs, params)
-
-    def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True):
-        """
-        Returns a list of oldforms.FormField instances for this field. It
-        calculates the choices at runtime, not at compile time.
-
-        name_prefix is a prefix to prepend to the "field_name" argument.
-        rel is a boolean specifying whether this field is in a related context.
-        """
-        field_objs, params = self.prepare_field_objs_and_params(manipulator, name_prefix)
-
-        # Add the "unique" validator(s).
-        for field_name_list in opts.unique_together:
-            if field_name_list[0] == self.name:
-                params['validator_list'].append(getattr(manipulator, 'isUnique%s' % '_'.join(field_name_list)))
-
-        # Add the "unique for..." validator(s).
-        if self.unique_for_date:
-            params['validator_list'].append(getattr(manipulator, 'isUnique%sFor%s' % (self.name, self.unique_for_date)))
-        if self.unique_for_month:
-            params['validator_list'].append(getattr(manipulator, 'isUnique%sFor%s' % (self.name, self.unique_for_month)))
-        if self.unique_for_year:
-            params['validator_list'].append(getattr(manipulator, 'isUnique%sFor%s' % (self.name, self.unique_for_year)))
-        if self.unique and not rel:
-            params['validator_list'].append(curry(manipulator_validator_unique, self, opts, manipulator))
-
-        # Only add is_required=True if the field cannot be blank. Primary keys
-        # are a special case, and fields in a related context should set this
-        # as False, because they'll be caught by a separate validator --
-        # RequiredIfOtherFieldGiven.
-        params['is_required'] = not self.blank and not self.primary_key and not rel
-
-        # BooleanFields (CheckboxFields) are a special case. They don't take
-        # is_required.
-        if isinstance(self, BooleanField):
-            del params['is_required']
-
-        # If this field is in a related context, check whether any other fields
-        # in the related object have core=True. If so, add a validator --
-        # RequiredIfOtherFieldsGiven -- to this FormField.
-        if rel and not self.blank and not isinstance(self, AutoField) and not isinstance(self, FileField):
-            # First, get the core fields, if any.
-            core_field_names = []
-            for f in opts.fields:
-                if f.core and f != self:
-                    core_field_names.extend(f.get_manipulator_field_names(name_prefix))
-            # Now, if there are any, add the validator to this FormField.
-            if core_field_names:
-                params['validator_list'].append(validators.RequiredIfOtherFieldsGiven(core_field_names, ugettext_lazy("This field is required.")))
-
-        # Finally, add the field_names.
-        field_names = self.get_manipulator_field_names(name_prefix)
-        return [man(field_name=field_names[i], **params) for i, man in enumerate(field_objs)]
-
     def get_validator_unique_lookup_type(self):
         return '%s__exact' % self.name
 
-    def get_manipulator_new_data(self, new_data, rel=False):
-        """
-        Given the full new_data dictionary (from the manipulator), returns this
-        field's data.
-        """
-        if rel:
-            return new_data.get(self.name, [self.get_default()])[0]
-        val = new_data.get(self.name, self.get_default())
-        if not self.empty_strings_allowed and val == '' and self.null:
-            val = None
-        return val
-
     def get_choices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH):
         """Returns choices with a default blank choices included, for use
         as SelectField choices for this field."""
@@ -366,19 +269,11 @@
         else:
             return self.get_default()
 
-    def flatten_data(self, follow, obj=None):
-        """
-        Returns a dictionary mapping the field's manipulator field names to its
-        "flattened" string values for the admin view. obj is the instance to
-        extract the values from.
-        """
-        return {self.attname: self._get_val_from_obj(obj)}
-
-    def get_follow(self, override=None):
-        if override != None:
-            return override
-        else:
-            return self.editable
+    def get_string_value(self, obj):
+        """
+        Returns a string value of this field from the passed obj.
+        """
+        return smart_unicode(self._get_val_from_obj(obj))
 
     def bind(self, fieldmapping, original, bound_field_class):
         return bound_field_class(self, fieldmapping, original)
@@ -439,22 +334,6 @@
             return None
         return int(value)
 
-    def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True):
-        if not rel:
-            return [] # Don't add a FormField unless it's in a related context.
-        return Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel, follow)
-
-    def get_manipulator_field_objs(self):
-        return [oldforms.HiddenField]
-
-    def get_manipulator_new_data(self, new_data, rel=False):
-        # Never going to be called
-        # Not in main change pages
-        # ignored in related context
-        if not rel:
-            return None
-        return Field.get_manipulator_new_data(self, new_data, rel)
-
     def contribute_to_class(self, cls, name):
         assert not cls._meta.has_auto_field, "A model can't have more than one AutoField."
         super(AutoField, self).contribute_to_class(cls, name)
@@ -485,18 +364,12 @@
             return None
         return bool(value)
 
-    def get_manipulator_field_objs(self):
-        return [oldforms.CheckboxField]
-
     def formfield(self, **kwargs):
         defaults = {'form_class': forms.BooleanField}
         defaults.update(kwargs)
         return super(BooleanField, self).formfield(**defaults)
 
 class CharField(Field):
-    def get_manipulator_field_objs(self):
-        return [oldforms.TextField]
-
     def get_internal_type(self):
         return "CharField"
 
@@ -517,8 +390,7 @@
 
 # TODO: Maybe move this into contrib, because it's specialized.
 class CommaSeparatedIntegerField(CharField):
-    def get_manipulator_field_objs(self):
-        return [oldforms.CommaSeparatedIntegerField]
+    pass
 
 class DateField(Field):
     empty_strings_allowed = False
@@ -562,13 +434,6 @@
             setattr(cls, 'get_previous_by_%s' % self.name,
                 curry(cls._get_next_or_previous_by_FIELD, field=self, is_next=False))
 
-    # Needed because of horrible auto_now[_add] behaviour wrt. editable
-    def get_follow(self, override=None):
-        if override != None:
-            return override
-        else:
-            return self.editable or self.auto_now or self.auto_now_add
-
     def get_db_prep_lookup(self, lookup_type, value):
         # For "__month" and "__day" lookups, convert the value to a string so
         # the database backend always sees a consistent type.
@@ -580,16 +445,13 @@
         # Casts dates into the format expected by the backend
         return connection.ops.value_to_db_date(self.to_python(value))
 
-    def get_manipulator_field_objs(self):
-        return [oldforms.DateField]
-
-    def flatten_data(self, follow, obj=None):
+    def get_string_value(self, obj):
         val = self._get_val_from_obj(obj)
         if val is None:
             data = ''
         else:
             data = datetime_safe.new_date(val).strftime("%Y-%m-%d")
-        return {self.attname: data}
+        return data
 
     def formfield(self, **kwargs):
         defaults = {'form_class': forms.DateField}
@@ -639,34 +501,14 @@
         # Casts dates into the format expected by the backend
         return connection.ops.value_to_db_datetime(self.to_python(value))
 
-    def get_manipulator_field_objs(self):
-        return [oldforms.DateField, oldforms.TimeField]
-
-    def get_manipulator_field_names(self, name_prefix):
-        return [name_prefix + self.name + '_date', name_prefix + self.name + '_time']
-
-    def get_manipulator_new_data(self, new_data, rel=False):
-        date_field, time_field = self.get_manipulator_field_names('')
-        if rel:
-            d = new_data.get(date_field, [None])[0]
-            t = new_data.get(time_field, [None])[0]
-        else:
-            d = new_data.get(date_field, None)
-            t = new_data.get(time_field, None)
-        if d is not None and t is not None:
-            return datetime.datetime.combine(d, t)
-        return self.get_default()
-
-    def flatten_data(self,follow, obj = None):
+    def get_string_value(self, obj):
         val = self._get_val_from_obj(obj)
-        date_field, time_field = self.get_manipulator_field_names('')
         if val is None:
-            date_data = time_data = ''
+            data = ''
         else:
             d = datetime_safe.new_datetime(val)
-            date_data = d.strftime('%Y-%m-%d')
-            time_data = d.strftime('%H:%M:%S')
-        return {date_field: date_data, time_field: time_data}
+            data = d.strftime('%Y-%m-%d %H:%M:%S')
+        return data
 
     def formfield(self, **kwargs):
         defaults = {'form_class': forms.DateTimeField}
@@ -715,9 +557,6 @@
         return connection.ops.value_to_db_decimal(self.to_python(value),
                 self.max_digits, self.decimal_places)
 
-    def get_manipulator_field_objs(self):
-        return [curry(oldforms.DecimalField, max_digits=self.max_digits, decimal_places=self.decimal_places)]
-
     def formfield(self, **kwargs):
         defaults = {
             'max_digits': self.max_digits,
@@ -732,9 +571,6 @@
         kwargs['max_length'] = kwargs.get('max_length', 75)
         CharField.__init__(self, *args, **kwargs)
 
-    def get_manipulator_field_objs(self):
-        return [oldforms.EmailField]
-
     def formfield(self, **kwargs):
         defaults = {'form_class': forms.EmailField}
         defaults.update(kwargs)
@@ -756,9 +592,6 @@
         defaults.update(kwargs)
         return super(FilePathField, self).formfield(**defaults)
 
-    def get_manipulator_field_objs(self):
-        return [curry(oldforms.FilePathField, path=self.path, match=self.match, recursive=self.recursive)]
-
     def get_internal_type(self):
         return "FilePathField"
 
@@ -770,9 +603,6 @@
             return None
         return float(value)
 
-    def get_manipulator_field_objs(self):
-        return [oldforms.FloatField]
-
     def get_internal_type(self):
         return "FloatField"
 
@@ -788,9 +618,6 @@
             return None
         return int(value)
 
-    def get_manipulator_field_objs(self):
-        return [oldforms.IntegerField]
-
     def get_internal_type(self):
         return "IntegerField"
 
@@ -813,9 +640,6 @@
         kwargs['max_length'] = 15
         Field.__init__(self, *args, **kwargs)
 
-    def get_manipulator_field_objs(self):
-        return [oldforms.IPAddressField]
-
     def get_internal_type(self):
         return "IPAddressField"
 
@@ -845,9 +669,6 @@
             return None
         return bool(value)
 
-    def get_manipulator_field_objs(self):
-        return [oldforms.NullBooleanField]
-
     def formfield(self, **kwargs):
         defaults = {
             'form_class': forms.NullBooleanField,
@@ -858,9 +679,6 @@
         return super(NullBooleanField, self).formfield(**defaults)
 
 class PhoneNumberField(Field):
-    def get_manipulator_field_objs(self):
-        return [oldforms.PhoneNumberField]
-
     def get_internal_type(self):
         return "PhoneNumberField"
 
@@ -871,9 +689,6 @@
         return super(PhoneNumberField, self).formfield(**defaults)
 
 class PositiveIntegerField(IntegerField):
-    def get_manipulator_field_objs(self):
-        return [oldforms.PositiveIntegerField]
-
     def get_internal_type(self):
         return "PositiveIntegerField"
 
@@ -883,9 +698,6 @@
         return super(PositiveIntegerField, self).formfield(**defaults)
 
 class PositiveSmallIntegerField(IntegerField):
-    def get_manipulator_field_objs(self):
-        return [oldforms.PositiveSmallIntegerField]
-
     def get_internal_type(self):
         return "PositiveSmallIntegerField"
 
@@ -897,7 +709,6 @@
 class SlugField(CharField):
     def __init__(self, *args, **kwargs):
         kwargs['max_length'] = kwargs.get('max_length', 50)
-        kwargs.setdefault('validator_list', []).append(validators.isSlug)
         # Set db_index=True unless it's been set manually.
         if 'db_index' not in kwargs:
             kwargs['db_index'] = True
@@ -907,23 +718,15 @@
         return "SlugField"
 
     def formfield(self, **kwargs):
-        defaults = {'form_class': forms.RegexField, 'regex': r'^[a-zA-Z0-9_-]+$',
-            'error_messages': {'invalid': _(u"Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens.")},
-        }
+        defaults = {'form_class': forms.SlugField}
         defaults.update(kwargs)
         return super(SlugField, self).formfield(**defaults)
 
 class SmallIntegerField(IntegerField):
-    def get_manipulator_field_objs(self):
-        return [oldforms.SmallIntegerField]
-
     def get_internal_type(self):
         return "SmallIntegerField"
 
 class TextField(Field):
-    def get_manipulator_field_objs(self):
-        return [oldforms.LargeTextField]
-
     def get_internal_type(self):
         return "TextField"
 
@@ -984,12 +787,13 @@
         # Casts times into the format expected by the backend
         return connection.ops.value_to_db_time(self.to_python(value))
 
-    def get_manipulator_field_objs(self):
-        return [oldforms.TimeField]
-
-    def flatten_data(self,follow, obj = None):
+    def get_string_value(self, obj):
         val = self._get_val_from_obj(obj)
-        return {self.attname: (val is not None and val.strftime("%H:%M:%S") or '')}
+        if val is None:
+            data = ''
+        else:
+            data = val.strftime("%H:%M:%S")
+        return data
 
     def formfield(self, **kwargs):
         defaults = {'form_class': forms.TimeField}
@@ -999,23 +803,15 @@
 class URLField(CharField):
     def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs):
         kwargs['max_length'] = kwargs.get('max_length', 200)
-        if verify_exists:
-            kwargs.setdefault('validator_list', []).append(validators.isExistingURL)
         self.verify_exists = verify_exists
         CharField.__init__(self, verbose_name, name, **kwargs)
 
-    def get_manipulator_field_objs(self):
-        return [oldforms.URLField]
-
     def formfield(self, **kwargs):
         defaults = {'form_class': forms.URLField, 'verify_exists': self.verify_exists}
         defaults.update(kwargs)
         return super(URLField, self).formfield(**defaults)
 
 class USStateField(Field):
-    def get_manipulator_field_objs(self):
-        return [oldforms.USStateField]
-
     def get_internal_type(self):
         return "USStateField"
 
@@ -1029,7 +825,3 @@
     def __init__(self, verbose_name=None, name=None, schema_path=None, **kwargs):
         self.schema_path = schema_path
         Field.__init__(self, verbose_name, name, **kwargs)
-
-    def get_manipulator_field_objs(self):
-        return [curry(oldforms.XMLLargeTextField, schema_path=self.schema_path)]
-

=== modified file 'django/db/models/fields/files.py'
--- django/db/models/fields/files.py	2008-08-10 21:10:47 +0000
+++ django/db/models/fields/files.py	2008-08-26 05:02:24 +0000
@@ -11,7 +11,6 @@
 from django.db.models import signals
 from django.utils.encoding import force_unicode, smart_str
 from django.utils.translation import ugettext_lazy, ugettext as _
-from django import oldforms
 from django import forms
 from django.core import validators
 from django.db.models.loading import cache
@@ -153,42 +152,6 @@
             return None
         return unicode(value)
 
-    def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True):
-        field_list = Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel, follow)
-        if not self.blank:
-            if rel:
-                # This validator makes sure FileFields work in a related context.
-                class RequiredFileField(object):
-                    def __init__(self, other_field_names, other_file_field_name):
-                        self.other_field_names = other_field_names
-                        self.other_file_field_name = other_file_field_name
-                        self.always_test = True
-                    def __call__(self, field_data, all_data):
-                        if not all_data.get(self.other_file_field_name, False):
-                            c = validators.RequiredIfOtherFieldsGiven(self.other_field_names, ugettext_lazy("This field is required."))
-                            c(field_data, all_data)
-                # First, get the core fields, if any.
-                core_field_names = []
-                for f in opts.fields:
-                    if f.core and f != self:
-                        core_field_names.extend(f.get_manipulator_field_names(name_prefix))
-                # Now, if there are any, add the validator to this FormField.
-                if core_field_names:
-                    field_list[0].validator_list.append(RequiredFileField(core_field_names, field_list[1].field_name))
-            else:
-                v = validators.RequiredIfOtherFieldNotGiven(field_list[1].field_name, ugettext_lazy("This field is required."))
-                v.always_test = True
-                field_list[0].validator_list.append(v)
-                field_list[0].is_required = field_list[1].is_required = False
-
-        # If the raw path is passed in, validate it's under the MEDIA_ROOT.
-        def isWithinMediaRoot(field_data, all_data):
-            f = os.path.abspath(os.path.join(settings.MEDIA_ROOT, field_data))
-            if not f.startswith(os.path.abspath(os.path.normpath(settings.MEDIA_ROOT))):
-                raise validators.ValidationError(_("Enter a valid filename."))
-        field_list[1].validator_list.append(isWithinMediaRoot)
-        return field_list
-
     def contribute_to_class(self, cls, name):
         super(FileField, self).contribute_to_class(cls, name)
         setattr(cls, self.name, FileDescriptor(self))
@@ -206,14 +169,9 @@
             # Otherwise, just close the file, so it doesn't tie up resources.
             file.close()
 
-    def get_manipulator_field_objs(self):
-        return [oldforms.FileUploadField, oldforms.HiddenField]
-
-    def get_manipulator_field_names(self, name_prefix):
-        return [name_prefix + self.name + '_file', name_prefix + self.name]
-
-    def save_file(self, new_data, new_object, original_object, change, rel, save=True):
-        upload_field_name = self.get_manipulator_field_names('')[0]
+    def save_file(self, new_data, new_object, original_object, change, rel,
+                  save=True):
+        upload_field_name = self.name + '_file'
         if new_data.get(upload_field_name, False):
             if rel:
                 file = new_data[upload_field_name][0]
@@ -282,9 +240,6 @@
         self.width_field, self.height_field = width_field, height_field
         FileField.__init__(self, verbose_name, name, **kwargs)
 
-    def get_manipulator_field_objs(self):
-        return [oldforms.ImageUploadField, oldforms.HiddenField]
-
     def formfield(self, **kwargs):
         defaults = {'form_class': forms.ImageField}
         defaults.update(kwargs)

=== modified file 'django/db/models/fields/related.py'
--- django/db/models/fields/related.py	2008-08-26 04:55:56 +0000
+++ django/db/models/fields/related.py	2008-08-26 05:02:24 +0000
@@ -4,10 +4,10 @@
 from django.db.models.related import RelatedObject
 from django.db.models.query import QuerySet
 from django.db.models.query_utils import QueryWrapper
+from django.utils.encoding import smart_unicode
 from django.utils.translation import ugettext_lazy, string_concat, ungettext, ugettext as _
 from django.utils.functional import curry
 from django.core import validators
-from django import oldforms
 from django import forms
 
 try:
@@ -83,14 +83,6 @@
 
 signals.class_prepared.connect(do_pending_lookups)
 
-def manipulator_valid_rel_key(f, self, field_data, all_data):
-    "Validates that the value is a valid foreign key"
-    klass = f.rel.to
-    try:
-        klass._default_manager.get(**{f.rel.field_name: field_data})
-    except klass.DoesNotExist:
-        raise validators.ValidationError, _("Please enter a valid %s.") % f.verbose_name
-
 #HACK
 class RelatedField(object):
     def contribute_to_class(self, cls, name):
@@ -670,15 +662,6 @@
     def get_validator_unique_lookup_type(self):
         return '%s__%s__exact' % (self.name, self.rel.get_related_field().name)
 
-    def prepare_field_objs_and_params(self, manipulator, name_prefix):
-        params = {'validator_list': self.validator_list[:], 'member_name': name_prefix + self.attname}
-        if self.null:
-            field_objs = [oldforms.NullSelectField]
-        else:
-            field_objs = [oldforms.SelectField]
-        params['choices'] = self.get_choices_default()
-        return field_objs, params
-
     def get_default(self):
         "Here we check if the default value is an object and return the to_field if so."
         field_default = super(ForeignKey, self).get_default()
@@ -686,17 +669,13 @@
             return getattr(field_default, self.rel.get_related_field().attname)
         return field_default
 
-    def get_manipulator_field_objs(self):
-        rel_field = self.rel.get_related_field()
-        return [oldforms.IntegerField]
-
     def get_db_prep_save(self, value):
         if value == '' or value == None:
             return None
         else:
             return self.rel.get_related_field().get_db_prep_save(value)
 
-    def flatten_data(self, follow, obj=None):
+    def get_string_value(self, obj):
         if not obj:
             # In required many-to-one fields with only one available choice,
             # select that one available choice. Note: For SelectFields
@@ -705,8 +684,8 @@
             if not self.blank and self.choices:
                 choice_list = self.get_choices_default()
                 if len(choice_list) == 2:
-                    return {self.attname: choice_list[1][0]}
-        return Field.flatten_data(self, follow, obj)
+                    return smart_unicode(choice_list[1][0])
+        return Field.get_string_value(self, obj)
 
     def contribute_to_class(self, cls, name):
         super(ForeignKey, self).contribute_to_class(cls, name)
@@ -786,10 +765,6 @@
         msg = ugettext_lazy('Hold down "Control", or "Command" on a Mac, to select more than one.')
         self.help_text = string_concat(self.help_text, ' ', msg)
 
-    def get_manipulator_field_objs(self):
-        choices = self.get_choices_default()
-        return [curry(oldforms.SelectMultipleField, size=min(max(len(choices), 5), 15), choices=choices)]
-
     def get_choices_default(self):
         return Field.get_choices(self, include_blank=False)
 
@@ -869,19 +844,19 @@
                 'value': len(badkeys) == 1 and badkeys[0] or tuple(badkeys),
             }
 
-    def flatten_data(self, follow, obj = None):
-        new_data = {}
+    def get_string_value(self, obj):
+        data = ''
         if obj:
-            instance_ids = [instance._get_pk_val() for instance in getattr(obj, self.name).all()]
-            new_data[self.name] = instance_ids
+            qs = getattr(obj, self.name).all()
+            data = [instance._get_pk_val() for instance in qs]
         else:
             # In required many-to-many fields with only one available choice,
             # select that one available choice.
             if not self.blank and not self.rel.edit_inline:
                 choices_list = self.get_choices_default()
                 if len(choices_list) == 1:
-                    new_data[self.name] = [choices_list[0][0]]
-        return new_data
+                    data = [choices_list[0][0]]
+        return smart_unicode(data)
 
     def contribute_to_class(self, cls, name):
         super(ManyToManyField, self).contribute_to_class(cls, name)

=== removed file 'django/db/models/manipulators.py'
--- django/db/models/manipulators.py	2008-08-08 20:59:02 +0000
+++ django/db/models/manipulators.py	1970-01-01 00:00:00 +0000
@@ -1,333 +0,0 @@
-from django.core.exceptions import ObjectDoesNotExist
-from django import oldforms
-from django.core import validators
-from django.db.models.fields import AutoField
-from django.db.models.fields.files import FileField
-from django.db.models import signals
-from django.utils.functional import curry
-from django.utils.datastructures import DotExpandedDict
-from django.utils.text import capfirst
-from django.utils.encoding import smart_str
-from django.utils.translation import ugettext as _
-from django.utils import datetime_safe
-
-def add_manipulators(sender, **kwargs):
-    cls = sender
-    cls.add_to_class('AddManipulator', AutomaticAddManipulator)
-    cls.add_to_class('ChangeManipulator', AutomaticChangeManipulator)
-
-signals.class_prepared.connect(add_manipulators)
-
-class ManipulatorDescriptor(object):
-    # This class provides the functionality that makes the default model
-    # manipulators (AddManipulator and ChangeManipulator) available via the
-    # model class.
-    def __init__(self, name, base):
-        self.man = None # Cache of the manipulator class.
-        self.name = name
-        self.base = base
-
-    def __get__(self, instance, model=None):
-        if instance != None:
-            raise AttributeError, "Manipulator cannot be accessed via instance"
-        else:
-            if not self.man:
-                # Create a class that inherits from the "Manipulator" class
-                # given in the model class (if specified) and the automatic
-                # manipulator.
-                bases = [self.base]
-                if hasattr(model, 'Manipulator'):
-                    bases = [model.Manipulator] + bases
-                self.man = type(self.name, tuple(bases), {})
-                self.man._prepare(model)
-            return self.man
-
-class AutomaticManipulator(oldforms.Manipulator):
-    def _prepare(cls, model):
-        cls.model = model
-        cls.manager = model._default_manager
-        cls.opts = model._meta
-        for field_name_list in cls.opts.unique_together:
-            setattr(cls, 'isUnique%s' % '_'.join(field_name_list), curry(manipulator_validator_unique_together, field_name_list, cls.opts))
-        for f in cls.opts.fields:
-            if f.unique_for_date:
-                setattr(cls, 'isUnique%sFor%s' % (f.name, f.unique_for_date), curry(manipulator_validator_unique_for_date, f, cls.opts.get_field(f.unique_for_date), cls.opts, 'date'))
-            if f.unique_for_month:
-                setattr(cls, 'isUnique%sFor%s' % (f.name, f.unique_for_month), curry(manipulator_validator_unique_for_date, f, cls.opts.get_field(f.unique_for_month), cls.opts, 'month'))
-            if f.unique_for_year:
-                setattr(cls, 'isUnique%sFor%s' % (f.name, f.unique_for_year), curry(manipulator_validator_unique_for_date, f, cls.opts.get_field(f.unique_for_year), cls.opts, 'year'))
-    _prepare = classmethod(_prepare)
-
-    def contribute_to_class(cls, other_cls, name):
-        setattr(other_cls, name, ManipulatorDescriptor(name, cls))
-    contribute_to_class = classmethod(contribute_to_class)
-
-    def __init__(self, follow=None):
-        self.follow = self.opts.get_follow(follow)
-        self.fields = []
-
-        for f in self.opts.fields + self.opts.many_to_many:
-            if self.follow.get(f.name, False):
-                self.fields.extend(f.get_manipulator_fields(self.opts, self, self.change))
-
-        # Add fields for related objects.
-        for f in self.opts.get_all_related_objects():
-            if self.follow.get(f.name, False):
-                fol = self.follow[f.name]
-                self.fields.extend(f.get_manipulator_fields(self.opts, self, self.change, fol))
-
-        # Add field for ordering.
-        if self.change and self.opts.get_ordered_objects():
-            self.fields.append(oldforms.CommaSeparatedIntegerField(field_name="order_"))
-
-    def save(self, new_data):
-        # TODO: big cleanup when core fields go -> use recursive manipulators.
-        params = {}
-        for f in self.opts.fields:
-            # Fields with auto_now_add should keep their original value in the change stage.
-            auto_now_add = self.change and getattr(f, 'auto_now_add', False)
-            if self.follow.get(f.name, None) and not auto_now_add:
-                param = f.get_manipulator_new_data(new_data)
-            else:
-                if self.change:
-                    param = getattr(self.original_object, f.attname)
-                else:
-                    param = f.get_default()
-            params[f.attname] = param
-
-        if self.change:
-            params[self.opts.pk.attname] = self.obj_key
-
-        # First, create the basic object itself.
-        new_object = self.model(**params)
-
-        # Now that the object's been created, save any uploaded files.
-        for f in self.opts.fields:
-            if isinstance(f, FileField):
-                f.save_file(new_data, new_object, self.change and self.original_object or None, self.change, rel=False, save=False)
-
-        # Now save the object
-        new_object.save()
-
-        # Calculate which primary fields have changed.
-        if self.change:
-            self.fields_added, self.fields_changed, self.fields_deleted = [], [], []
-            for f in self.opts.fields:
-                if not f.primary_key and smart_str(getattr(self.original_object, f.attname)) != smart_str(getattr(new_object, f.attname)):
-                    self.fields_changed.append(f.verbose_name)
-
-        # Save many-to-many objects. Example: Set sites for a poll.
-        for f in self.opts.many_to_many:
-            if self.follow.get(f.name, None):
-                if not f.rel.edit_inline:
-                    new_vals = new_data.getlist(f.name)
-                    # First, clear the existing values.
-                    rel_manager = getattr(new_object, f.name)
-                    rel_manager.clear()
-                    # Then, set the new values.
-                    for n in new_vals:
-                        rel_manager.add(f.rel.to._default_manager.get(pk=n))
-                    # TODO: Add to 'fields_changed'
-
-        expanded_data = DotExpandedDict(dict(new_data))
-        # Save many-to-one objects. Example: Add the Choice objects for a Poll.
-        for related in self.opts.get_all_related_objects():
-            # Create obj_list, which is a DotExpandedDict such as this:
-            # [('0', {'id': ['940'], 'choice': ['This is the first choice']}),
-            #  ('1', {'id': ['941'], 'choice': ['This is the second choice']}),
-            #  ('2', {'id': [''], 'choice': ['']})]
-            child_follow = self.follow.get(related.name, None)
-
-            if child_follow:
-                obj_list = expanded_data.get(related.var_name, {}).items()
-                if not obj_list:
-                    continue
-
-                obj_list.sort(lambda x, y: cmp(int(x[0]), int(y[0])))
-
-                # For each related item...
-                for _, rel_new_data in obj_list:
-
-                    params = {}
-
-                    # Keep track of which core=True fields were provided.
-                    # If all core fields were given, the related object will be saved.
-                    # If none of the core fields were given, the object will be deleted.
-                    # If some, but not all, of the fields were given, the validator would
-                    # have caught that.
-                    all_cores_given, all_cores_blank = True, True
-
-                    # Get a reference to the old object. We'll use it to compare the
-                    # old to the new, to see which fields have changed.
-                    old_rel_obj = None
-                    if self.change:
-                        if rel_new_data[related.opts.pk.name][0]:
-                            try:
-                                old_rel_obj = getattr(self.original_object, related.get_accessor_name()).get(**{'%s__exact' % related.opts.pk.name: rel_new_data[related.opts.pk.attname][0]})
-                            except ObjectDoesNotExist:
-                                pass
-
-                    for f in related.opts.fields:
-                        if f.core and not isinstance(f, FileField) and f.get_manipulator_new_data(rel_new_data, rel=True) in (None, ''):
-                            all_cores_given = False
-                        elif f.core and not isinstance(f, FileField) and f.get_manipulator_new_data(rel_new_data, rel=True) not in (None, ''):
-                            all_cores_blank = False
-                        # If this field isn't editable, give it the same value it had
-                        # previously, according to the given ID. If the ID wasn't
-                        # given, use a default value. FileFields are also a special
-                        # case, because they'll be dealt with later.
-
-                        if f == related.field:
-                            param = getattr(new_object, related.field.rel.get_related_field().attname)
-                        elif (not self.change) and isinstance(f, AutoField):
-                            param = None
-                        elif self.change and (isinstance(f, FileField) or not child_follow.get(f.name, None)):
-                            if old_rel_obj:
-                                param = getattr(old_rel_obj, f.column)
-                            else:
-                                param = f.get_default()
-                        else:
-                            param = f.get_manipulator_new_data(rel_new_data, rel=True)
-                        if param != None:
-                            params[f.attname] = param
-
-                    # Create the related item.
-                    new_rel_obj = related.model(**params)
-
-                    # If all the core fields were provided (non-empty), save the item.
-                    if all_cores_given:
-                        new_rel_obj.save()
-
-                        # Save any uploaded files.
-                        for f in related.opts.fields:
-                            if child_follow.get(f.name, None):
-                                if isinstance(f, FileField) and rel_new_data.get(f.name, False):
-                                    f.save_file(rel_new_data, new_rel_obj, self.change and old_rel_obj or None, old_rel_obj is not None, rel=True)
-
-                        # Calculate whether any fields have changed.
-                        if self.change:
-                            if not old_rel_obj: # This object didn't exist before.
-                                self.fields_added.append('%s "%s"' % (related.opts.verbose_name, new_rel_obj))
-                            else:
-                                for f in related.opts.fields:
-                                    if not f.primary_key and f != related.field and smart_str(getattr(old_rel_obj, f.attname)) != smart_str(getattr(new_rel_obj, f.attname)):
-                                        self.fields_changed.append('%s for %s "%s"' % (f.verbose_name, related.opts.verbose_name, new_rel_obj))
-
-                        # Save many-to-many objects.
-                        for f in related.opts.many_to_many:
-                            if child_follow.get(f.name, None) and not f.rel.edit_inline:
-                                new_value = rel_new_data[f.attname]
-                                setattr(new_rel_obj, f.name, f.rel.to.objects.filter(pk__in=new_value))
-                                if self.change:
-                                    self.fields_changed.append('%s for %s "%s"' % (f.verbose_name, related.opts.verbose_name, new_rel_obj))
-
-                    # If, in the change stage, all of the core fields were blank and
-                    # the primary key (ID) was provided, delete the item.
-                    if self.change and all_cores_blank and old_rel_obj:
-                        new_rel_obj.delete()
-                        self.fields_deleted.append('%s "%s"' % (related.opts.verbose_name, old_rel_obj))
-
-        # Save the order, if applicable.
-        if self.change and self.opts.get_ordered_objects():
-            order = new_data['order_'] and map(int, new_data['order_'].split(',')) or []
-            for rel_opts in self.opts.get_ordered_objects():
-                getattr(new_object, 'set_%s_order' % rel_opts.object_name.lower())(order)
-        return new_object
-
-    def get_related_objects(self):
-        return self.opts.get_followed_related_objects(self.follow)
-
-    def flatten_data(self):
-        new_data = {}
-        obj = self.change and self.original_object or None
-        for f in self.opts.get_data_holders(self.follow):
-            fol = self.follow.get(f.name)
-            new_data.update(f.flatten_data(fol, obj))
-        return new_data
-
-class AutomaticAddManipulator(AutomaticManipulator):
-    change = False
-
-class AutomaticChangeManipulator(AutomaticManipulator):
-    change = True
-    def __init__(self, obj_key, follow=None):
-        self.obj_key = obj_key
-        try:
-            self.original_object = self.manager.get(pk=obj_key)
-        except ObjectDoesNotExist:
-            # If the object doesn't exist, this might be a manipulator for a
-            # one-to-one related object that hasn't created its subobject yet.
-            # For example, this might be a Restaurant for a Place that doesn't
-            # yet have restaurant information.
-            if self.opts.one_to_one_field:
-                # Sanity check -- Make sure the "parent" object exists.
-                # For example, make sure the Place exists for the Restaurant.
-                # Let the ObjectDoesNotExist exception propagate up.
-                limit_choices_to = self.opts.one_to_one_field.rel.limit_choices_to
-                lookup_kwargs = {'%s__exact' % self.opts.one_to_one_field.rel.field_name: obj_key}
-                self.opts.one_to_one_field.rel.to.get_model_module().complex_filter(limit_choices_to).get(**lookup_kwargs)
-                params = dict([(f.attname, f.get_default()) for f in self.opts.fields])
-                params[self.opts.pk.attname] = obj_key
-                self.original_object = self.opts.get_model_module().Klass(**params)
-            else:
-                raise
-        super(AutomaticChangeManipulator, self).__init__(follow=follow)
-
-def manipulator_validator_unique_together(field_name_list, opts, self, field_data, all_data):
-    from django.db.models.fields.related import ManyToOneRel
-    from django.utils.text import get_text_list
-    field_list = [opts.get_field(field_name) for field_name in field_name_list]
-    if isinstance(field_list[0].rel, ManyToOneRel):
-        kwargs = {'%s__%s__iexact' % (field_name_list[0], field_list[0].rel.field_name): field_data}
-    else:
-        kwargs = {'%s__iexact' % field_name_list[0]: field_data}
-    for f in field_list[1:]:
-        # This is really not going to work for fields that have different
-        # form fields, e.g. DateTime.
-        # This validation needs to occur after html2python to be effective.
-        field_val = all_data.get(f.name, None)
-        if field_val is None:
-            # This will be caught by another validator, assuming the field
-            # doesn't have blank=True.
-            return
-        if isinstance(f.rel, ManyToOneRel):
-            kwargs['%s__pk' % f.name] = field_val
-        else:
-            kwargs['%s__iexact' % f.name] = field_val
-    try:
-        old_obj = self.manager.get(**kwargs)
-    except ObjectDoesNotExist:
-        return
-    if hasattr(self, 'original_object') and self.original_object._get_pk_val() == old_obj._get_pk_val():
-        pass
-    else:
-        raise validators.ValidationError, _("%(object)s with this %(type)s already exists for the given %(field)s.") % \
-            {'object': capfirst(opts.verbose_name), 'type': field_list[0].verbose_name, 'field': get_text_list([f.verbose_name for f in field_list[1:]], _('and'))}
-
-def manipulator_validator_unique_for_date(from_field, date_field, opts, lookup_type, self, field_data, all_data):
-    from django.db.models.fields.related import ManyToOneRel
-    date_str = all_data.get(date_field.get_manipulator_field_names('')[0], None)
-    date_val = oldforms.DateField.html2python(date_str)
-    if date_val is None:
-        return # Date was invalid. This will be caught by another validator.
-    lookup_kwargs = {'%s__year' % date_field.name: date_val.year}
-    if isinstance(from_field.rel, ManyToOneRel):
-        lookup_kwargs['%s__pk' % from_field.name] = field_data
-    else:
-        lookup_kwargs['%s__iexact' % from_field.name] = field_data
-    if lookup_type in ('month', 'date'):
-        lookup_kwargs['%s__month' % date_field.name] = date_val.month
-    if lookup_type == 'date':
-        lookup_kwargs['%s__day' % date_field.name] = date_val.day
-    try:
-        old_obj = self.manager.get(**lookup_kwargs)
-    except ObjectDoesNotExist:
-        return
-    else:
-        if hasattr(self, 'original_object') and self.original_object._get_pk_val() == old_obj._get_pk_val():
-            pass
-        else:
-            format_string = (lookup_type == 'date') and '%B %d, %Y' or '%B %Y'
-            date_val = datetime_safe.new_datetime(date_val)
-            raise validators.ValidationError, "Please enter a different %s. The one you entered is already being used for %s." % \
-                (from_field.verbose_name, date_val.strftime(format_string))

=== modified file 'django/db/models/options.py'
--- django/db/models/options.py	2008-07-18 23:54:34 +0000
+++ django/db/models/options.py	2008-08-26 05:02:24 +0000
@@ -396,28 +396,6 @@
             self._related_many_to_many_cache = cache
         return cache
 
-    def get_followed_related_objects(self, follow=None):
-        if follow == None:
-            follow = self.get_follow()
-        return [f for f in self.get_all_related_objects() if follow.get(f.name, None)]
-
-    def get_data_holders(self, follow=None):
-        if follow == None:
-            follow = self.get_follow()
-        return [f for f in self.fields + self.many_to_many + self.get_all_related_objects() if follow.get(f.name, None)]
-
-    def get_follow(self, override=None):
-        follow = {}
-        for f in self.fields + self.many_to_many + self.get_all_related_objects():
-            if override and f.name in override:
-                child_override = override[f.name]
-            else:
-                child_override = None
-            fol = f.get_follow(child_override)
-            if fol != None:
-                follow[f.name] = fol
-        return follow
-
     def get_base_chain(self, model):
         """
         Returns a list of parent classes leading to 'model' (order from closet
@@ -459,28 +437,3 @@
             #        objects.append(opts)
             self._ordered_objects = objects
         return self._ordered_objects
-
-    def has_field_type(self, field_type, follow=None):
-        """
-        Returns True if this object's admin form has at least one of the given
-        field_type (e.g. FileField).
-        """
-        # TODO: follow
-        if not hasattr(self, '_field_types'):
-            self._field_types = {}
-        if field_type not in self._field_types:
-            try:
-                # First check self.fields.
-                for f in self.fields:
-                    if isinstance(f, field_type):
-                        raise StopIteration
-                # Failing that, check related fields.
-                for related in self.get_followed_related_objects(follow):
-                    for f in related.opts.fields:
-                        if isinstance(f, field_type):
-                            raise StopIteration
-            except StopIteration:
-                self._field_types[field_type] = True
-            else:
-                self._field_types[field_type] = False
-        return self._field_types[field_type]

=== modified file 'django/db/models/related.py'
--- django/db/models/related.py	2007-03-10 07:37:08 +0000
+++ django/db/models/related.py	2008-08-26 05:02:24 +0000
@@ -19,28 +19,6 @@
         self.name = '%s:%s' % (self.opts.app_label, self.opts.module_name)
         self.var_name = self.opts.object_name.lower()
 
-    def flatten_data(self, follow, obj=None):
-        new_data = {}
-        rel_instances = self.get_list(obj)
-        for i, rel_instance in enumerate(rel_instances):
-            instance_data = {}
-            for f in self.opts.fields + self.opts.many_to_many:
-                # TODO: Fix for recursive manipulators.
-                fol = follow.get(f.name, None)
-                if fol:
-                    field_data = f.flatten_data(fol, rel_instance)
-                    for name, value in field_data.items():
-                        instance_data['%s.%d.%s' % (self.var_name, i, name)] = value
-            new_data.update(instance_data)
-        return new_data
-
-    def extract_data(self, data):
-        """
-        Pull out the data meant for inline objects of this class,
-        i.e. anything starting with our module name.
-        """
-        return data # TODO
-
     def get_list(self, parent_instance=None):
         "Get the list of this type of object from an instance of the parent class."
         if parent_instance is not None:
@@ -76,52 +54,11 @@
     def get_db_prep_lookup(self, lookup_type, value):
         # Defer to the actual field definition for db prep
         return self.field.get_db_prep_lookup(lookup_type, value)
-        
+
     def editable_fields(self):
         "Get the fields in this class that should be edited inline."
         return [f for f in self.opts.fields + self.opts.many_to_many if f.editable and f != self.field]
 
-    def get_follow(self, override=None):
-        if isinstance(override, bool):
-            if override:
-                over = {}
-            else:
-                return None
-        else:
-            if override:
-                over = override.copy()
-            elif self.edit_inline:
-                over = {}
-            else:
-                return None
-
-        over[self.field.name] = False
-        return self.opts.get_follow(over)
-
-    def get_manipulator_fields(self, opts, manipulator, change, follow):
-        if self.field.rel.multiple:
-            if change:
-                attr = getattr(manipulator.original_object, self.get_accessor_name())
-                count = attr.count()
-                count += self.field.rel.num_extra_on_change
-            else:
-                count = self.field.rel.num_in_admin
-            if self.field.rel.min_num_in_admin:
-                count = max(count, self.field.rel.min_num_in_admin)
-            if self.field.rel.max_num_in_admin:
-                count = min(count, self.field.rel.max_num_in_admin)
-        else:
-            count = 1
-
-        fields = []
-        for i in range(count):
-            for f in self.opts.fields + self.opts.many_to_many:
-                if follow.get(f.name, False):
-                    prefix = '%s.%d.' % (self.var_name, i)
-                    fields.extend(f.get_manipulator_fields(self.opts, manipulator, change,
-                                                           name_prefix=prefix, rel=True))
-        return fields
-
     def __repr__(self):
         return "<RelatedObject: %s related to %s>" % (self.name, self.field.name)
 

=== modified file 'django/forms/fields.py'
--- django/forms/fields.py	2008-08-23 17:36:42 +0000
+++ django/forms/fields.py	2008-08-26 05:02:24 +0000
@@ -38,7 +38,7 @@
     'RegexField', 'EmailField', 'FileField', 'ImageField', 'URLField',
     'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField',
     'ComboField', 'MultiValueField', 'FloatField', 'DecimalField',
-    'SplitDateTimeField', 'IPAddressField', 'FilePathField',
+    'SplitDateTimeField', 'IPAddressField', 'FilePathField', 'SlugField',
 )
 
 # These values, if given to to_python(), will trigger the self.required check.
@@ -835,3 +835,14 @@
 
     def __init__(self, *args, **kwargs):
         super(IPAddressField, self).__init__(ipv4_re, *args, **kwargs)
+
+slug_re = re.compile(r'^[-\w]+$')
+
+class SlugField(RegexField):
+    default_error_messages = {
+        'invalid': _(u"Enter a valid 'slug' consisting of letters, numbers,"
+                     u" underscores or hyphens."),
+    }
+
+    def __init__(self, *args, **kwargs):
+        super(SlugField, self).__init__(slug_re, *args, **kwargs)

=== removed directory 'django/oldforms'
=== removed file 'django/oldforms/__init__.py'
--- django/oldforms/__init__.py	2008-08-02 04:56:11 +0000
+++ django/oldforms/__init__.py	1970-01-01 00:00:00 +0000
@@ -1,1056 +0,0 @@
-from django.core import validators
-from django.core.exceptions import PermissionDenied
-from django.utils.html import escape
-from django.utils.safestring import mark_safe
-from django.conf import settings
-from django.utils.translation import ugettext, ungettext
-from django.utils.encoding import smart_unicode, force_unicode
-
-FORM_FIELD_ID_PREFIX = 'id_'
-
-class EmptyValue(Exception):
-    "This is raised when empty data is provided"
-    pass
-
-class Manipulator(object):
-    # List of permission strings. User must have at least one to manipulate.
-    # None means everybody has permission.
-    required_permission = ''
-
-    def __init__(self):
-        # List of FormField objects
-        self.fields = []
-
-    def __getitem__(self, field_name):
-        "Looks up field by field name; raises KeyError on failure"
-        for field in self.fields:
-            if field.field_name == field_name:
-                return field
-        raise KeyError, "Field %s not found\n%s" % (field_name, repr(self.fields))
-
-    def __delitem__(self, field_name):
-        "Deletes the field with the given field name; raises KeyError on failure"
-        for i, field in enumerate(self.fields):
-            if field.field_name == field_name:
-                del self.fields[i]
-                return
-        raise KeyError, "Field %s not found" % field_name
-
-    def check_permissions(self, user):
-        """Confirms user has required permissions to use this manipulator; raises
-        PermissionDenied on failure."""
-        if self.required_permission is None:
-            return
-        if user.has_perm(self.required_permission):
-            return
-        raise PermissionDenied
-
-    def prepare(self, new_data):
-        """
-        Makes any necessary preparations to new_data, in place, before data has
-        been validated.
-        """
-        for field in self.fields:
-            field.prepare(new_data)
-
-    def get_validation_errors(self, new_data):
-        "Returns dictionary mapping field_names to error-message lists"
-        errors = {}
-        self.prepare(new_data)
-        for field in self.fields:
-            errors.update(field.get_validation_errors(new_data))
-            val_name = 'validate_%s' % field.field_name
-            if hasattr(self, val_name):
-                val = getattr(self, val_name)
-                try:
-                    field.run_validator(new_data, val)
-                except (validators.ValidationError, validators.CriticalValidationError), e:
-                    errors.setdefault(field.field_name, []).extend(e.messages)
-
-#            if field.is_required and not new_data.get(field.field_name, False):
-#                errors.setdefault(field.field_name, []).append(ugettext_lazy('This field is required.'))
-#                continue
-#            try:
-#                validator_list = field.validator_list
-#                if hasattr(self, 'validate_%s' % field.field_name):
-#                    validator_list.append(getattr(self, 'validate_%s' % field.field_name))
-#                for validator in validator_list:
-#                    if field.is_required or new_data.get(field.field_name, False) or hasattr(validator, 'always_test'):
-#                        try:
-#                            if hasattr(field, 'requires_data_list'):
-#                                validator(new_data.getlist(field.field_name), new_data)
-#                            else:
-#                                validator(new_data.get(field.field_name, ''), new_data)
-#                        except validators.ValidationError, e:
-#                            errors.setdefault(field.field_name, []).extend(e.messages)
-#            # If a CriticalValidationError is raised, ignore any other ValidationErrors
-#            # for this particular field
-#            except validators.CriticalValidationError, e:
-#                errors.setdefault(field.field_name, []).extend(e.messages)
-        return errors
-
-    def save(self, new_data):
-        "Saves the changes and returns the new object"
-        # changes is a dictionary-like object keyed by field_name
-        raise NotImplementedError
-
-    def do_html2python(self, new_data):
-        """
-        Convert the data from HTML data types to Python datatypes, changing the
-        object in place. This happens after validation but before storage. This
-        must happen after validation because html2python functions aren't
-        expected to deal with invalid input.
-        """
-        for field in self.fields:
-            field.convert_post_data(new_data)
-
-class FormWrapper(object):
-    """
-    A wrapper linking a Manipulator to the template system.
-    This allows dictionary-style lookups of formfields. It also handles feeding
-    prepopulated data and validation error messages to the formfield objects.
-    """
-    def __init__(self, manipulator, data=None, error_dict=None, edit_inline=True):
-        self.manipulator = manipulator
-        if data is None:
-            data = {}
-        if error_dict is None:
-            error_dict = {}
-        self.data = data
-        self.error_dict = error_dict
-        self._inline_collections = None
-        self.edit_inline = edit_inline
-
-    def __repr__(self):
-        return repr(self.__dict__)
-
-    def __getitem__(self, key):
-        for field in self.manipulator.fields:
-            if field.field_name == key:
-                data = field.extract_data(self.data)
-                return FormFieldWrapper(field, data, self.error_dict.get(field.field_name, []))
-        if self.edit_inline:
-            self.fill_inline_collections()
-            for inline_collection in self._inline_collections:
-                # The 'orig_name' comparison is for backwards compatibility
-                # with hand-crafted forms.
-                if inline_collection.name == key or (':' not in key and inline_collection.orig_name == key):
-                    return inline_collection
-        raise KeyError, "Could not find Formfield or InlineObjectCollection named %r" % key
-
-    def fill_inline_collections(self):
-        if not self._inline_collections:
-            ic = []
-            related_objects = self.manipulator.get_related_objects()
-            for rel_obj in related_objects:
-                data = rel_obj.extract_data(self.data)
-                inline_collection = InlineObjectCollection(self.manipulator, rel_obj, data, self.error_dict)
-                ic.append(inline_collection)
-            self._inline_collections = ic
-
-    def has_errors(self):
-        return self.error_dict != {}
-
-    def _get_fields(self):
-        try:
-            return self._fields
-        except AttributeError:
-            self._fields = [self.__getitem__(field.field_name) for field in self.manipulator.fields]
-            return self._fields
-
-    fields = property(_get_fields)
-
-class FormFieldWrapper(object):
-    "A bridge between the template system and an individual form field. Used by FormWrapper."
-    def __init__(self, formfield, data, error_list):
-        self.formfield, self.data, self.error_list = formfield, data, error_list
-        self.field_name = self.formfield.field_name # for convenience in templates
-
-    def __str__(self):
-        "Renders the field"
-        return unicode(self).encode('utf-8')
-
-    def __unicode__(self):
-        "Renders the field"
-        return force_unicode(self.formfield.render(self.data))
-
-    def __repr__(self):
-        return '<FormFieldWrapper for "%s">' % self.formfield.field_name
-
-    def field_list(self):
-        """
-        Like __str__(), but returns a list. Use this when the field's render()
-        method returns a list.
-        """
-        return self.formfield.render(self.data)
-
-    def errors(self):
-        return self.error_list
-
-    def html_error_list(self):
-        if self.errors():
-            return mark_safe('<ul class="errorlist"><li>%s</li></ul>' % '</li><li>'.join([escape(e) for e in self.errors()]))
-        else:
-            return mark_safe('')
-
-    def get_id(self):
-        return self.formfield.get_id()
-
-class FormFieldCollection(FormFieldWrapper):
-    "A utility class that gives the template access to a dict of FormFieldWrappers"
-    def __init__(self, formfield_dict):
-        self.formfield_dict = formfield_dict
-
-    def __str__(self):
-        return unicode(self).encode('utf-8')
-
-    def __unicode__(self):
-        return unicode(self.formfield_dict)
-
-    def __getitem__(self, template_key):
-        "Look up field by template key; raise KeyError on failure"
-        return self.formfield_dict[template_key]
-
-    def __repr__(self):
-        return "<FormFieldCollection: %s>" % self.formfield_dict
-
-    def errors(self):
-        "Returns list of all errors in this collection's formfields"
-        errors = []
-        for field in self.formfield_dict.values():
-            if hasattr(field, 'errors'):
-                errors.extend(field.errors())
-        return errors
-
-    def has_errors(self):
-        return bool(len(self.errors()))
-
-    def html_combined_error_list(self):
-        return mark_safe(''.join([field.html_error_list() for field in self.formfield_dict.values() if hasattr(field, 'errors')]))
-
-class InlineObjectCollection(object):
-    "An object that acts like a sparse list of form field collections."
-    def __init__(self, parent_manipulator, rel_obj, data, errors):
-        self.parent_manipulator = parent_manipulator
-        self.rel_obj = rel_obj
-        self.data = data
-        self.errors = errors
-        self._collections = None
-        self.name = rel_obj.name
-        # This is the name used prior to fixing #1839. Needs for backwards
-        # compatibility.
-        self.orig_name = rel_obj.opts.module_name
-
-    def __len__(self):
-        self.fill()
-        return self._collections.__len__()
-
-    def __getitem__(self, k):
-        self.fill()
-        return self._collections.__getitem__(k)
-
-    def __setitem__(self, k, v):
-        self.fill()
-        return self._collections.__setitem__(k,v)
-
-    def __delitem__(self, k):
-        self.fill()
-        return self._collections.__delitem__(k)
-
-    def __iter__(self):
-        self.fill()
-        return iter(self._collections.values())
-
-    def items(self):
-        self.fill()
-        return self._collections.items()
-
-    def fill(self):
-        if self._collections:
-            return
-        else:
-            var_name = self.rel_obj.opts.object_name.lower()
-            collections = {}
-            orig = None
-            if hasattr(self.parent_manipulator, 'original_object'):
-                orig = self.parent_manipulator.original_object
-            orig_list = self.rel_obj.get_list(orig)
-
-            for i, instance in enumerate(orig_list):
-                collection = {'original': instance}
-                for f in self.rel_obj.editable_fields():
-                    for field_name in f.get_manipulator_field_names(''):
-                        full_field_name = '%s.%d.%s' % (var_name, i, field_name)
-                        field = self.parent_manipulator[full_field_name]
-                        data = field.extract_data(self.data)
-                        errors = self.errors.get(full_field_name, [])
-                        collection[field_name] = FormFieldWrapper(field, data, errors)
-                collections[i] = FormFieldCollection(collection)
-            self._collections = collections
-
-
-class FormField(object):
-    """Abstract class representing a form field.
-
-    Classes that extend FormField should define the following attributes:
-        field_name
-            The field's name for use by programs.
-        validator_list
-            A list of validation tests (callback functions) that the data for
-            this field must pass in order to be added or changed.
-        is_required
-            A Boolean. Is it a required field?
-    Subclasses should also implement a render(data) method, which is responsible
-    for rending the form field in XHTML.
-    """
-
-    def __str__(self):
-        return unicode(self).encode('utf-8')
-
-    def __unicode__(self):
-        return self.render(u'')
-
-    def __repr__(self):
-        return 'FormField "%s"' % self.field_name
-
-    def prepare(self, new_data):
-        "Hook for doing something to new_data (in place) before validation."
-        pass
-
-    def html2python(data):
-        "Hook for converting an HTML datatype (e.g. 'on' for checkboxes) to a Python type"
-        return data
-    html2python = staticmethod(html2python)
-
-    def render(self, data):
-        raise NotImplementedError
-
-    def get_member_name(self):
-        if hasattr(self, 'member_name'):
-            return self.member_name
-        else:
-            return self.field_name
-
-    def extract_data(self, data_dict):
-        if hasattr(self, 'requires_data_list') and hasattr(data_dict, 'getlist'):
-            data = data_dict.getlist(self.get_member_name())
-        else:
-            data = data_dict.get(self.get_member_name(), None)
-        if data is None:
-            data = ''
-        return data
-
-    def convert_post_data(self, new_data):
-        name = self.get_member_name()
-        if self.field_name in new_data:
-            d = new_data.getlist(self.field_name)
-            try:
-                converted_data = [self.__class__.html2python(data) for data in d]
-            except ValueError:
-                converted_data = d
-            new_data.setlist(name, converted_data)
-        else:
-            try:
-                #individual fields deal with None values themselves
-                new_data.setlist(name, [self.__class__.html2python(None)])
-            except EmptyValue:
-                new_data.setlist(name, [])
-
-
-    def run_validator(self, new_data, validator):
-        if self.is_required or new_data.get(self.field_name, False) or hasattr(validator, 'always_test'):
-            if hasattr(self, 'requires_data_list'):
-                validator(new_data.getlist(self.field_name), new_data)
-            else:
-                validator(new_data.get(self.field_name, ''), new_data)
-
-    def get_validation_errors(self, new_data):
-        errors = {}
-        if self.is_required and not new_data.get(self.field_name, False):
-            errors.setdefault(self.field_name, []).append(ugettext('This field is required.'))
-            return errors
-        try:
-            for validator in self.validator_list:
-                try:
-                    self.run_validator(new_data, validator)
-                except validators.ValidationError, e:
-                    errors.setdefault(self.field_name, []).extend(e.messages)
-        # If a CriticalValidationError is raised, ignore any other ValidationErrors
-        # for this particular field
-        except validators.CriticalValidationError, e:
-            errors.setdefault(self.field_name, []).extend(e.messages)
-        return errors
-
-    def get_id(self):
-        "Returns the HTML 'id' attribute for this form field."
-        return FORM_FIELD_ID_PREFIX + self.field_name
-
-####################
-# GENERIC WIDGETS  #
-####################
-
-class TextField(FormField):
-    input_type = "text"
-    def __init__(self, field_name, length=30, max_length=None, is_required=False, validator_list=None, member_name=None):
-        if validator_list is None: validator_list = []
-        self.field_name = field_name
-        self.length, self.max_length = length, max_length
-        self.is_required = is_required
-        self.validator_list = [self.isValidLength, self.hasNoNewlines] + validator_list
-        if member_name != None:
-            self.member_name = member_name
-
-    def isValidLength(self, data, form):
-        if data and self.max_length and len(smart_unicode(data)) > self.max_length:
-            raise validators.ValidationError, ungettext("Ensure your text is less than %s character.",
-                "Ensure your text is less than %s characters.", self.max_length) % self.max_length
-
-    def hasNoNewlines(self, data, form):
-        if data and '\n' in data:
-            raise validators.ValidationError, ugettext("Line breaks are not allowed here.")
-
-    def render(self, data):
-        if data is None:
-            data = u''
-        max_length = u''
-        if self.max_length:
-            max_length = u'maxlength="%s" ' % self.max_length
-        return mark_safe(u'<input type="%s" id="%s" class="v%s%s" name="%s" size="%s" value="%s" %s/>' % \
-            (self.input_type, self.get_id(), self.__class__.__name__, self.is_required and u' required' or '',
-            self.field_name, self.length, escape(data), max_length))
-
-    def html2python(data):
-        return data
-    html2python = staticmethod(html2python)
-
-class PasswordField(TextField):
-    input_type = "password"
-
-class LargeTextField(TextField):
-    def __init__(self, field_name, rows=10, cols=40, is_required=False, validator_list=None, max_length=None):
-        if validator_list is None: validator_list = []
-        self.field_name = field_name
-        self.rows, self.cols, self.is_required = rows, cols, is_required
-        self.validator_list = validator_list[:]
-        if max_length:
-            self.validator_list.append(self.isValidLength)
-            self.max_length = max_length
-
-    def render(self, data):
-        if data is None:
-            data = ''
-        return mark_safe(u'<textarea id="%s" class="v%s%s" name="%s" rows="%s" cols="%s">%s</textarea>' % \
-            (self.get_id(), self.__class__.__name__, self.is_required and u' required' or u'',
-            self.field_name, self.rows, self.cols, escape(data)))
-
-class HiddenField(FormField):
-    def __init__(self, field_name, is_required=False, validator_list=None, max_length=None):
-        if validator_list is None: validator_list = []
-        self.field_name, self.is_required = field_name, is_required
-        self.validator_list = validator_list[:]
-
-    def render(self, data):
-        return mark_safe(u'<input type="hidden" id="%s" name="%s" value="%s" />' % \
-            (self.get_id(), self.field_name, escape(data)))
-
-class CheckboxField(FormField):
-    def __init__(self, field_name, checked_by_default=False, validator_list=None, is_required=False):
-        if validator_list is None: validator_list = []
-        self.field_name = field_name
-        self.checked_by_default = checked_by_default
-        self.is_required = is_required
-        self.validator_list = validator_list[:]
-
-    def render(self, data):
-        checked_html = ''
-        if data or (data is '' and self.checked_by_default):
-            checked_html = ' checked="checked"'
-        return mark_safe(u'<input type="checkbox" id="%s" class="v%s" name="%s"%s />' % \
-            (self.get_id(), self.__class__.__name__,
-            self.field_name, checked_html))
-
-    def html2python(data):
-        "Convert value from browser ('on' or '') to a Python boolean"
-        if data == 'on':
-            return True
-        return False
-    html2python = staticmethod(html2python)
-
-class SelectField(FormField):
-    def __init__(self, field_name, choices=None, size=1, is_required=False, validator_list=None, member_name=None):
-        if validator_list is None: validator_list = []
-        if choices is None: choices = []
-        choices = [(k, smart_unicode(v, strings_only=True)) for k, v in choices]
-        self.field_name = field_name
-        # choices is a list of (value, human-readable key) tuples because order matters
-        self.choices, self.size, self.is_required = choices, size, is_required
-        self.validator_list = [self.isValidChoice] + validator_list
-        if member_name != None:
-            self.member_name = member_name
-
-    def render(self, data):
-        output = [u'<select id="%s" class="v%s%s" name="%s" size="%s">' % \
-            (self.get_id(), self.__class__.__name__,
-             self.is_required and u' required' or u'', self.field_name, self.size)]
-        str_data = smart_unicode(data) # normalize to string
-        for value, display_name in self.choices:
-            selected_html = u''
-            if smart_unicode(value) == str_data:
-                selected_html = u' selected="selected"'
-            output.append(u'    <option value="%s"%s>%s</option>' % (escape(value), selected_html, force_unicode(escape(display_name))))
-        output.append(u'  </select>')
-        return mark_safe(u'\n'.join(output))
-
-    def isValidChoice(self, data, form):
-        str_data = smart_unicode(data)
-        str_choices = [smart_unicode(item[0]) for item in self.choices]
-        if str_data not in str_choices:
-            raise validators.ValidationError, ugettext("Select a valid choice; '%(data)s' is not in %(choices)s.") % {'data': str_data, 'choices': str_choices}
-
-class NullSelectField(SelectField):
-    "This SelectField converts blank fields to None"
-    def html2python(data):
-        if not data:
-            return None
-        return data
-    html2python = staticmethod(html2python)
-
-class RadioSelectField(FormField):
-    def __init__(self, field_name, choices=None, ul_class='', is_required=False, validator_list=None, member_name=None):
-        if validator_list is None: validator_list = []
-        if choices is None: choices = []
-        choices = [(k, smart_unicode(v)) for k, v in choices]
-        self.field_name = field_name
-        # choices is a list of (value, human-readable key) tuples because order matters
-        self.choices, self.is_required = choices, is_required
-        self.validator_list = [self.isValidChoice] + validator_list
-        self.ul_class = ul_class
-        if member_name != None:
-            self.member_name = member_name
-
-    def render(self, data):
-        """
-        Returns a special object, RadioFieldRenderer, that is iterable *and*
-        has a default unicode() rendered output.
-
-        This allows for flexible use in templates. You can just use the default
-        rendering:
-
-            {{ field_name }}
-
-        ...which will output the radio buttons in an unordered list.
-        Or, you can manually traverse each radio option for special layout:
-
-            {% for option in field_name.field_list %}
-                {{ option.field }} {{ option.label }}<br />
-            {% endfor %}
-        """
-        class RadioFieldRenderer:
-            def __init__(self, datalist, ul_class):
-                self.datalist, self.ul_class = datalist, ul_class
-            def __unicode__(self):
-                "Default unicode() output for this radio field -- a <ul>"
-                output = [u'<ul%s>' % (self.ul_class and u' class="%s"' % self.ul_class or u'')]
-                output.extend([u'<li>%s %s</li>' % (d['field'], d['label']) for d in self.datalist])
-                output.append(u'</ul>')
-                return mark_safe(u''.join(output))
-            def __iter__(self):
-                for d in self.datalist:
-                    yield d
-            def __len__(self):
-                return len(self.datalist)
-        datalist = []
-        str_data = smart_unicode(data) # normalize to string
-        for i, (value, display_name) in enumerate(self.choices):
-            selected_html = ''
-            if smart_unicode(value) == str_data:
-                selected_html = u' checked="checked"'
-            datalist.append({
-                'value': value,
-                'name': display_name,
-                'field': mark_safe(u'<input type="radio" id="%s" name="%s" value="%s"%s/>' % \
-                    (self.get_id() + u'_' + unicode(i), self.field_name, value, selected_html)),
-                'label': mark_safe(u'<label for="%s">%s</label>' % \
-                    (self.get_id() + u'_' + unicode(i), display_name),
-            )})
-        return RadioFieldRenderer(datalist, self.ul_class)
-
-    def isValidChoice(self, data, form):
-        str_data = smart_unicode(data)
-        str_choices = [smart_unicode(item[0]) for item in self.choices]
-        if str_data not in str_choices:
-            raise validators.ValidationError, ugettext("Select a valid choice; '%(data)s' is not in %(choices)s.") % {'data':str_data, 'choices':str_choices}
-
-class NullBooleanField(SelectField):
-    "This SelectField provides 'Yes', 'No' and 'Unknown', mapping results to True, False or None"
-    def __init__(self, field_name, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        SelectField.__init__(self, field_name, choices=[('1', ugettext('Unknown')), ('2', ugettext('Yes')), ('3', ugettext('No'))],
-            is_required=is_required, validator_list=validator_list)
-
-    def render(self, data):
-        if data is None: data = '1'
-        elif data == True: data = '2'
-        elif data == False: data = '3'
-        return SelectField.render(self, data)
-
-    def html2python(data):
-        return {None: None, '1': None, '2': True, '3': False}[data]
-    html2python = staticmethod(html2python)
-
-class SelectMultipleField(SelectField):
-    requires_data_list = True
-    def render(self, data):
-        output = [u'<select id="%s" class="v%s%s" name="%s" size="%s" multiple="multiple">' % \
-            (self.get_id(), self.__class__.__name__, self.is_required and u' required' or u'',
-            self.field_name, self.size)]
-        str_data_list = map(smart_unicode, data) # normalize to strings
-        for value, choice in self.choices:
-            selected_html = u''
-            if smart_unicode(value) in str_data_list:
-                selected_html = u' selected="selected"'
-            output.append(u'    <option value="%s"%s>%s</option>' % (escape(value), selected_html, force_unicode(escape(choice))))
-        output.append(u'  </select>')
-        return mark_safe(u'\n'.join(output))
-
-    def isValidChoice(self, field_data, all_data):
-        # data is something like ['1', '2', '3']
-        str_choices = [smart_unicode(item[0]) for item in self.choices]
-        for val in map(smart_unicode, field_data):
-            if val not in str_choices:
-                raise validators.ValidationError, ugettext("Select a valid choice; '%(data)s' is not in %(choices)s.") % {'data':val, 'choices':str_choices}
-
-    def html2python(data):
-        if data is None:
-            raise EmptyValue
-        return data
-    html2python = staticmethod(html2python)
-
-class CheckboxSelectMultipleField(SelectMultipleField):
-    """
-    This has an identical interface to SelectMultipleField, except the rendered
-    widget is different. Instead of a <select multiple>, this widget outputs a
-    <ul> of <input type="checkbox">es.
-
-    Of course, that results in multiple form elements for the same "single"
-    field, so this class's prepare() method flattens the split data elements
-    back into the single list that validators, renderers and save() expect.
-    """
-    requires_data_list = True
-    def __init__(self, field_name, choices=None, ul_class='', validator_list=None):
-        if validator_list is None: validator_list = []
-        if choices is None: choices = []
-        self.ul_class = ul_class
-        SelectMultipleField.__init__(self, field_name, choices, size=1, is_required=False, validator_list=validator_list)
-
-    def prepare(self, new_data):
-        # new_data has "split" this field into several fields, so flatten it
-        # back into a single list.
-        data_list = []
-        for value, readable_value in self.choices:
-            if new_data.get('%s%s' % (self.field_name, value), '') == 'on':
-                data_list.append(value)
-        new_data.setlist(self.field_name, data_list)
-
-    def render(self, data):
-        output = [u'<ul%s>' % (self.ul_class and u' class="%s"' % self.ul_class or u'')]
-        str_data_list = map(smart_unicode, data) # normalize to strings
-        for value, choice in self.choices:
-            checked_html = u''
-            if smart_unicode(value) in str_data_list:
-                checked_html = u' checked="checked"'
-            field_name = u'%s%s' % (self.field_name, value)
-            output.append(u'<li><input type="checkbox" id="%s" class="v%s" name="%s"%s value="on" /> <label for="%s">%s</label></li>' % \
-                (self.get_id() + escape(value), self.__class__.__name__, field_name, checked_html,
-                self.get_id() + escape(value), choice))
-        output.append(u'</ul>')
-        return mark_safe(u'\n'.join(output))
-
-####################
-# FILE UPLOADS     #
-####################
-
-class FileUploadField(FormField):
-    def __init__(self, field_name, is_required=False, validator_list=None, max_length=None):
-        if validator_list is None: validator_list = []
-        self.field_name, self.is_required = field_name, is_required
-        self.validator_list = [self.isNonEmptyFile] + validator_list
-
-    def isNonEmptyFile(self, new_data, all_data):
-        if hasattr(new_data, 'upload_errors'):
-            upload_errors = new_data.upload_errors()
-            if upload_errors:
-                raise validators.CriticalValidationError, upload_errors
-        try:
-            file_size = new_data.size
-        except AttributeError:
-            file_size = len(new_data['content'])
-        if not file_size:
-            raise validators.CriticalValidationError, ugettext("The submitted file is empty.")
-
-    def render(self, data):
-        return mark_safe(u'<input type="file" id="%s" class="v%s" name="%s" />' % \
-            (self.get_id(), self.__class__.__name__, self.field_name))
-
-    def prepare(self, new_data):
-        if hasattr(new_data, 'upload_errors'):
-            upload_errors = new_data.upload_errors()
-            new_data[self.field_name] = { '_file_upload_error': upload_errors }
-
-    def html2python(data):
-        if data is None:
-            raise EmptyValue
-        return data
-    html2python = staticmethod(html2python)
-
-class ImageUploadField(FileUploadField):
-    "A FileUploadField that raises CriticalValidationError if the uploaded file isn't an image."
-    def __init__(self, *args, **kwargs):
-        FileUploadField.__init__(self, *args, **kwargs)
-        self.validator_list.insert(0, self.isValidImage)
-
-    def isValidImage(self, field_data, all_data):
-        try:
-            validators.isValidImage(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-####################
-# INTEGERS/FLOATS  #
-####################
-
-class IntegerField(TextField):
-    def __init__(self, field_name, length=10, max_length=None, is_required=False, validator_list=None, member_name=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isInteger] + validator_list
-        if member_name is not None:
-            self.member_name = member_name
-        TextField.__init__(self, field_name, length, max_length, is_required, validator_list)
-
-    def isInteger(self, field_data, all_data):
-        try:
-            validators.isInteger(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-    def html2python(data):
-        if data == '' or data is None:
-            return None
-        return int(data)
-    html2python = staticmethod(html2python)
-
-class SmallIntegerField(IntegerField):
-    def __init__(self, field_name, length=5, max_length=5, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isSmallInteger] + validator_list
-        IntegerField.__init__(self, field_name, length, max_length, is_required, validator_list)
-
-    def isSmallInteger(self, field_data, all_data):
-        if not -32768 <= int(field_data) <= 32767:
-            raise validators.CriticalValidationError, ugettext("Enter a whole number between -32,768 and 32,767.")
-
-class PositiveIntegerField(IntegerField):
-    def __init__(self, field_name, length=10, max_length=None, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isPositive] + validator_list
-        IntegerField.__init__(self, field_name, length, max_length, is_required, validator_list)
-
-    def isPositive(self, field_data, all_data):
-        if int(field_data) < 0:
-            raise validators.CriticalValidationError, ugettext("Enter a positive number.")
-
-class PositiveSmallIntegerField(IntegerField):
-    def __init__(self, field_name, length=5, max_length=None, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isPositiveSmall] + validator_list
-        IntegerField.__init__(self, field_name, length, max_length, is_required, validator_list)
-
-    def isPositiveSmall(self, field_data, all_data):
-        if not 0 <= int(field_data) <= 32767:
-            raise validators.CriticalValidationError, ugettext("Enter a whole number between 0 and 32,767.")
-
-class FloatField(TextField):
-    def __init__(self, field_name, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [validators.isValidFloat] + validator_list
-        TextField.__init__(self, field_name, is_required=is_required, validator_list=validator_list)
-
-    def html2python(data):
-        if data == '' or data is None:
-            return None
-        return float(data)
-    html2python = staticmethod(html2python)
-
-class DecimalField(TextField):
-    def __init__(self, field_name, max_digits, decimal_places, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        self.max_digits, self.decimal_places = max_digits, decimal_places
-        validator_list = [self.isValidDecimal] + validator_list
-        # Initialise the TextField, making sure it's large enough to fit the number with a - sign and a decimal point.
-        super(DecimalField, self).__init__(field_name, max_digits+2, max_digits+2, is_required, validator_list)
-
-    def isValidDecimal(self, field_data, all_data):
-        v = validators.IsValidDecimal(self.max_digits, self.decimal_places)
-        try:
-            v(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-    def html2python(data):
-        if data == '' or data is None:
-            return None
-        try:
-            import decimal
-        except ImportError:
-            from django.utils import _decimal as decimal
-        try:
-            return decimal.Decimal(data)
-        except decimal.InvalidOperation, e:
-            raise ValueError, e
-    html2python = staticmethod(html2python)
-
-####################
-# DATES AND TIMES  #
-####################
-
-class DatetimeField(TextField):
-    """A FormField that automatically converts its data to a datetime.datetime object.
-    The data should be in the format YYYY-MM-DD HH:MM:SS."""
-    def __init__(self, field_name, length=30, max_length=None, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        self.field_name = field_name
-        self.length, self.max_length = length, max_length
-        self.is_required = is_required
-        self.validator_list = [validators.isValidANSIDatetime] + validator_list
-
-    def html2python(data):
-        "Converts the field into a datetime.datetime object"
-        import datetime
-        try:
-            date, time = data.split()
-            y, m, d = date.split('-')
-            timebits = time.split(':')
-            h, mn = timebits[:2]
-            if len(timebits) > 2:
-                s = int(timebits[2])
-            else:
-                s = 0
-            return datetime.datetime(int(y), int(m), int(d), int(h), int(mn), s)
-        except ValueError:
-            return None
-    html2python = staticmethod(html2python)
-
-class DateField(TextField):
-    """A FormField that automatically converts its data to a datetime.date object.
-    The data should be in the format YYYY-MM-DD."""
-    def __init__(self, field_name, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isValidDate] + validator_list
-        TextField.__init__(self, field_name, length=10, max_length=10,
-            is_required=is_required, validator_list=validator_list)
-
-    def isValidDate(self, field_data, all_data):
-        try:
-            validators.isValidANSIDate(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-    def html2python(data):
-        "Converts the field into a datetime.date object"
-        import time, datetime
-        try:
-            time_tuple = time.strptime(data, '%Y-%m-%d')
-            return datetime.date(*time_tuple[0:3])
-        except (ValueError, TypeError):
-            return None
-    html2python = staticmethod(html2python)
-
-class TimeField(TextField):
-    """A FormField that automatically converts its data to a datetime.time object.
-    The data should be in the format HH:MM:SS or HH:MM:SS.mmmmmm."""
-    def __init__(self, field_name, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isValidTime] + validator_list
-        TextField.__init__(self, field_name, length=8, max_length=8,
-            is_required=is_required, validator_list=validator_list)
-
-    def isValidTime(self, field_data, all_data):
-        try:
-            validators.isValidANSITime(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-    def html2python(data):
-        "Converts the field into a datetime.time object"
-        import time, datetime
-        try:
-            part_list = data.split('.')
-            try:
-                time_tuple = time.strptime(part_list[0], '%H:%M:%S')
-            except ValueError: # seconds weren't provided
-                time_tuple = time.strptime(part_list[0], '%H:%M')
-            t = datetime.time(*time_tuple[3:6])
-            if (len(part_list) == 2):
-                t = t.replace(microsecond=int(part_list[1]))
-            return t
-        except (ValueError, TypeError, AttributeError):
-            return None
-    html2python = staticmethod(html2python)
-
-####################
-# INTERNET-RELATED #
-####################
-
-class EmailField(TextField):
-    "A convenience FormField for validating e-mail addresses"
-    def __init__(self, field_name, length=50, max_length=75, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isValidEmail] + validator_list
-        TextField.__init__(self, field_name, length, max_length=max_length,
-            is_required=is_required, validator_list=validator_list)
-
-    def isValidEmail(self, field_data, all_data):
-        try:
-            validators.isValidEmail(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-class URLField(TextField):
-    "A convenience FormField for validating URLs"
-    def __init__(self, field_name, length=50, max_length=200, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isValidURL] + validator_list
-        TextField.__init__(self, field_name, length=length, max_length=max_length,
-            is_required=is_required, validator_list=validator_list)
-
-    def isValidURL(self, field_data, all_data):
-        try:
-            validators.isValidURL(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-class IPAddressField(TextField):
-    def __init__(self, field_name, length=15, max_length=15, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isValidIPAddress] + validator_list
-        TextField.__init__(self, field_name, length=length, max_length=max_length,
-            is_required=is_required, validator_list=validator_list)
-
-    def isValidIPAddress(self, field_data, all_data):
-        try:
-            validators.isValidIPAddress4(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-    def html2python(data):
-        return data or None
-    html2python = staticmethod(html2python)
-
-####################
-# MISCELLANEOUS    #
-####################
-
-class FilePathField(SelectField):
-    "A SelectField whose choices are the files in a given directory."
-    def __init__(self, field_name, path, match=None, recursive=False, is_required=False, validator_list=None, max_length=None):
-        import os
-        from django.db.models import BLANK_CHOICE_DASH
-        if match is not None:
-            import re
-            match_re = re.compile(match)
-        choices = not is_required and BLANK_CHOICE_DASH[:] or []
-        if recursive:
-            for root, dirs, files in os.walk(path):
-                for f in files:
-                    if match is None or match_re.search(f):
-                        f = os.path.join(root, f)
-                        choices.append((f, f.replace(path, "", 1)))
-        else:
-            try:
-                for f in os.listdir(path):
-                    full_file = os.path.join(path, f)
-                    if os.path.isfile(full_file) and (match is None or match_re.search(f)):
-                        choices.append((full_file, f))
-            except OSError:
-                pass
-        SelectField.__init__(self, field_name, choices, 1, is_required, validator_list)
-
-class PhoneNumberField(TextField):
-    "A convenience FormField for validating phone numbers (e.g. '630-555-1234')"
-    def __init__(self, field_name, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isValidPhone] + validator_list
-        TextField.__init__(self, field_name, length=12, max_length=12,
-            is_required=is_required, validator_list=validator_list)
-
-    def isValidPhone(self, field_data, all_data):
-        try:
-            validators.isValidPhone(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-class USStateField(TextField):
-    "A convenience FormField for validating U.S. states (e.g. 'IL')"
-    def __init__(self, field_name, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isValidUSState] + validator_list
-        TextField.__init__(self, field_name, length=2, max_length=2,
-            is_required=is_required, validator_list=validator_list)
-
-    def isValidUSState(self, field_data, all_data):
-        try:
-            validators.isValidUSState(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-    def html2python(data):
-        if data:
-            return data.upper() # Should always be stored in upper case
-        return data
-    html2python = staticmethod(html2python)
-
-class CommaSeparatedIntegerField(TextField):
-    "A convenience FormField for validating comma-separated integer fields"
-    def __init__(self, field_name, max_length=None, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isCommaSeparatedIntegerList] + validator_list
-        TextField.__init__(self, field_name, length=20, max_length=max_length,
-            is_required=is_required, validator_list=validator_list)
-
-    def isCommaSeparatedIntegerList(self, field_data, all_data):
-        try:
-            validators.isCommaSeparatedIntegerList(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-    def render(self, data):
-        if data is None:
-            data = u''
-        elif isinstance(data, (list, tuple)):
-            data = u','.join(data)
-        return super(CommaSeparatedIntegerField, self).render(data)
-
-class RawIdAdminField(CommaSeparatedIntegerField):
-    def html2python(data):
-        if data:
-            return data.split(',')
-        else:
-            return []
-    html2python = staticmethod(html2python)
-
-class XMLLargeTextField(LargeTextField):
-    """
-    A LargeTextField with an XML validator. The schema_path argument is the
-    full path to a Relax NG compact schema to validate against.
-    """
-    def __init__(self, field_name, schema_path, **kwargs):
-        self.schema_path = schema_path
-        kwargs.setdefault('validator_list', []).insert(0, self.isValidXML)
-        LargeTextField.__init__(self, field_name, **kwargs)
-
-    def isValidXML(self, field_data, all_data):
-        v = validators.RelaxNGCompact(self.schema_path)
-        try:
-            v(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages

=== modified file 'docs/howto/custom-model-fields.txt'
--- docs/howto/custom-model-fields.txt	2008-08-24 09:25:19 +0000
+++ docs/howto/custom-model-fields.txt	2008-08-26 05:02:24 +0000
@@ -108,11 +108,11 @@
 All of Django's fields (and when we say *fields* in this document, we always
 mean model fields and not :ref:`form fields <ref-forms-fields>`) are subclasses
 of :class:`django.db.models.Field`. Most of the information that Django records
-about a field is common to all fields -- name, help text, validator lists,
-uniqueness and so forth. Storing all that information is handled by ``Field``.
-We'll get into the precise details of what ``Field`` can do later on; for now,
-suffice it to say that everything descends from ``Field`` and then customizes
-key pieces of the class behavior.
+about a field is common to all fields -- name, help text, uniqueness and so
+forth. Storing all that information is handled by ``Field``. We'll get into the
+precise details of what ``Field`` can do later on; for now, suffice it to say
+that everything descends from ``Field`` and then customizes key pieces of the
+class behavior.
 
 It's important to realize that a Django field class is not what is stored in
 your model attributes. The model attributes contain normal Python objects. The
@@ -212,7 +212,6 @@
     * :attr:`~django.db.models.Field.unique_for_date`
     * :attr:`~django.db.models.Field.unique_for_month`
     * :attr:`~django.db.models.Field.unique_for_year`
-    * :attr:`~django.db.models.Field.validator_list`
     * :attr:`~django.db.models.Field.choices`
     * :attr:`~django.db.models.Field.help_text`
     * :attr:`~django.db.models.Field.db_column`
@@ -569,33 +568,19 @@
 Converting field data for serialization
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. method:: flatten_data(self, follow, obj=None)
-
-.. admonition:: Subject to change
-
-    Although implementing this method is necessary to allow field
-    serialization, the API might change in the future.
-
-Returns a dictionary, mapping the field's attribute name to a flattened string
-version of the data. This method has some internal uses that aren't of interest
-to use here (mostly having to do with forms). For our purposes, it's sufficient
-to return a one item dictionary that maps the attribute name to a string.
+.. method:: get_string_value(self, obj)
 
 This method is used by the serializers to convert the field into a string for
-output. You can ignore the input parameters for serialization purposes, although
-calling :meth:`Field._get_val_from_obj(obj)
-<django.db.models.Field._get_val_from_obj>` is the best way to get the value to
-serialize.
-
-For example, since our ``HandField`` uses strings for its data storage anyway,
-we can reuse some existing conversion code::
+output. Calling :meth:``Field._get_val_from_obj(obj)`` is the best way to get the
+value to serialize. For example, since our ``HandField`` uses strings for its
+data storage anyway, we can reuse some existing conversion code::
 
     class HandField(models.Field):
         # ...
 
-        def flatten_data(self, follow, obj=None):
+        def get_string_value(self, obj):
             value = self._get_val_from_obj(obj)
-            return {self.attname: self.get_db_prep_value(value)}
+            return self.get_db_prep_value(value)
 
 Some general advice
 --------------------

=== removed file 'docs/obsolete/forms.txt'
--- docs/obsolete/forms.txt	2008-08-23 22:25:40 +0000
+++ docs/obsolete/forms.txt	1970-01-01 00:00:00 +0000
@@ -1,692 +0,0 @@
-.. _obsolete-forms:
-
-===============================
-Forms, fields, and manipulators
-===============================
-
-Forwards-compatibility note
-===========================
-
-The legacy forms/manipulators system described in this document is going to be
-replaced in the next Django release. If you're starting from scratch, we
-strongly encourage you not to waste your time learning this. Instead, learn and
-use the new :ref:`forms library <topics-forms-index>`.
-
-Introduction
-============
-
-Once you've got a chance to play with Django's admin interface, you'll probably
-wonder if the fantastic form validation framework it uses is available to user
-code. It is, and this document explains how the framework works.
-
-We'll take a top-down approach to examining Django's form validation framework,
-because much of the time you won't need to use the lower-level APIs. Throughout
-this document, we'll be working with the following model, a "place" object::
-
-    from django.db import models
-
-    PLACE_TYPES = (
-        (1, 'Bar'),
-        (2, 'Restaurant'),
-        (3, 'Movie Theater'),
-        (4, 'Secret Hideout'),
-    )
-
-    class Place(models.Model):
-        name = models.CharField(max_length=100)
-        address = models.CharField(max_length=100, blank=True)
-        city = models.CharField(max_length=50, blank=True)
-        state = models.USStateField()
-        zip_code = models.CharField(max_length=5, blank=True)
-        place_type = models.IntegerField(choices=PLACE_TYPES)
-
-        class Admin:
-            pass
-
-        def __unicode__(self):
-            return self.name
-
-Defining the above class is enough to create an admin interface to a ``Place``,
-but what if you want to allow public users to submit places?
-
-Automatic Manipulators
-======================
-
-The highest-level interface for object creation and modification is the
-**automatic Manipulator** framework. An automatic manipulator is a utility
-class tied to a given model that "knows" how to create or modify instances of
-that model and how to validate data for the object. Automatic Manipulators come
-in two flavors: ``AddManipulators`` and ``ChangeManipulators``. Functionally
-they are quite similar, but the former knows how to create new instances of the
-model, while the latter modifies existing instances. Both types of classes are
-automatically created when you define a new class::
-
-    >>> from mysite.myapp.models import Place
-    >>> Place.AddManipulator
-    <class 'django.models.manipulators.AddManipulator'>
-    >>> Place.ChangeManipulator
-    <class 'django.models.manipulators.ChangeManipulator'>
-
-Using the ``AddManipulator``
-----------------------------
-
-We'll start with the ``AddManipulator``.  Here's a very simple view that takes
-POSTed data from the browser and creates a new ``Place`` object::
-
-    from django.shortcuts import render_to_response
-    from django.http import Http404, HttpResponse, HttpResponseRedirect
-    from django import oldforms as forms
-    from mysite.myapp.models import Place
-
-    def naive_create_place(request):
-        """A naive approach to creating places; don't actually use this!"""
-        # Create the AddManipulator.
-        manipulator = Place.AddManipulator()
-
-        # Make a copy of the POSTed data so that do_html2python can
-        # modify it in place (request.POST is immutable).
-        new_data = request.POST.copy()
-
-        # Convert the request data (which will all be strings) into the
-        # appropriate Python types for those fields.
-        manipulator.do_html2python(new_data)
-
-        # Save the new object.
-        new_place = manipulator.save(new_data)
-
-        # It worked!
-        return HttpResponse("Place created: %s" % new_place)
-
-The ``naive_create_place`` example works, but as you probably can tell, this
-view has a number of problems:
-
-    * No validation of any sort is performed. If, for example, the ``name`` field
-      isn't given in ``request.POST``, the save step will cause a database error
-      because that field is required. Ugly.
-
-    * Even if you *do* perform validation, there's still no way to give that
-      information to the user in any sort of useful way.
-
-    * You'll have to separately create a form (and view) that submits to this
-      page, which is a pain and is redundant.
-
-Let's dodge these problems momentarily to take a look at how you could create a
-view with a form that submits to this flawed creation view::
-
-    def naive_create_place_form(request):
-        """Simplistic place form view; don't actually use anything like this!"""
-        # Create a FormWrapper object that the template can use. Ignore
-        # the last two arguments to FormWrapper for now.
-        form = forms.FormWrapper(Place.AddManipulator(), {}, {})
-        return render_to_response('places/naive_create_form.html', {'form': form})
-
-(This view, as well as all the following ones, has the same imports as in the
-first example above.)
-
-The ``forms.FormWrapper`` object is a wrapper that templates can
-easily deal with to create forms. Here's the ``naive_create_form.html``
-template::
-
-    {% extends "base.html" %}
-
-    {% block content %}
-    <h1>Create a place:</h1>
-
-    <form method="post" action="../do_new/">
-    <p><label for="id_name">Name:</label> {{ form.name }}</p>
-    <p><label for="id_address">Address:</label> {{ form.address }}</p>
-    <p><label for="id_city">City:</label> {{ form.city }}</p>
-    <p><label for="id_state">State:</label> {{ form.state }}</p>
-    <p><label for="id_zip_code">Zip:</label> {{ form.zip_code }}</p>
-    <p><label for="id_place_type">Place type:</label> {{ form.place_type }}</p>
-    <input type="submit" />
-    </form>
-    {% endblock %}
-
-Before we get back to the problems with these naive set of views, let's go over
-some salient points of the above template:
-
-    * Field "widgets" are handled for you: ``{{ form.field }}`` automatically
-      creates the "right" type of widget for the form, as you can see with the
-      ``place_type`` field above.
-
-    * There isn't a way just to spit out the form. You'll still need to define
-      how the form gets laid out. This is a feature: Every form should be
-      designed differently. Django doesn't force you into any type of mold.
-      If you must use tables, use tables. If you're a semantic purist, you can
-      probably find better HTML than in the above template.
-
-    * To avoid name conflicts, the ``id`` values of form elements take the
-      form "id_*fieldname*".
-
-By creating a creation form we've solved problem number 3 above, but we still
-don't have any validation. Let's revise the validation issue by writing a new
-creation view that takes validation into account::
-
-    def create_place_with_validation(request):
-        manipulator = Place.AddManipulator()
-        new_data = request.POST.copy()
-
-        # Check for validation errors
-        errors = manipulator.get_validation_errors(new_data)
-        manipulator.do_html2python(new_data)
-        if errors:
-            return render_to_response('places/errors.html', {'errors': errors})
-        else:
-            new_place = manipulator.save(new_data)
-            return HttpResponse("Place created: %s" % new_place)
-
-In this new version, errors will be found -- ``manipulator.get_validation_errors``
-handles all the validation for you -- and those errors can be nicely presented
-on an error page (templated, of course)::
-
-    {% extends "base.html" %}
-
-    {% block content %}
-
-    <h1>Please go back and correct the following error{{ errors|pluralize }}:</h1>
-    <ul>
-        {% for e in errors.items %}
-        <li>Field "{{ e.0 }}": {{ e.1|join:", " }}</li>
-        {% endfor %}
-    </ul>
-
-    {% endblock %}
-
-Still, this has its own problems:
-
-    * There's still the issue of creating a separate (redundant) view for the
-      submission form.
-
-    * Errors, though nicely presented, are on a separate page, so the user will
-      have to use the "back" button to fix errors. That's ridiculous and unusable.
-
-The best way to deal with these issues is to collapse the two views -- the form
-and the submission -- into a single view.  This view will be responsible for
-creating the form, validating POSTed data, and creating the new object (if the
-data is valid). An added bonus of this approach is that errors and the form will
-both be available on the same page, so errors with fields can be presented in
-context.
-
-.. admonition:: Philosophy:
-
-    Finally, for the HTTP purists in the audience (and the authorship), this
-    nicely matches the "true" meanings of HTTP GET and HTTP POST: GET fetches
-    the form, and POST creates the new object.
-
-Below is the finished view::
-
-    def create_place(request):
-        manipulator = Place.AddManipulator()
-
-        if request.method == 'POST':
-            # If data was POSTed, we're trying to create a new Place.
-            new_data = request.POST.copy()
-
-            # Check for errors.
-            errors = manipulator.get_validation_errors(new_data)
-            manipulator.do_html2python(new_data)
-
-            if not errors:
-                # No errors. This means we can save the data!
-                new_place = manipulator.save(new_data)
-
-                # Redirect to the object's "edit" page. Always use a redirect
-                # after POST data, so that reloads don't accidentally create
-                # duplicate entries, and so users don't see the confusing
-                # "Repost POST data?" alert box in their browsers.
-                return HttpResponseRedirect("/places/edit/%i/" % new_place.id)
-        else:
-            # No POST, so we want a brand new form without any data or errors.
-            errors = new_data = {}
-
-        # Create the FormWrapper, template, context, response.
-        form = forms.FormWrapper(manipulator, new_data, errors)
-        return render_to_response('places/create_form.html', {'form': form})
-
-and here's the ``create_form`` template::
-
-    {% extends "base.html" %}
-
-    {% block content %}
-    <h1>Create a place:</h1>
-
-    {% if form.has_errors %}
-    <h2>Please correct the following error{{ form.error_dict|pluralize }}:</h2>
-    {% endif %}
-
-    <form method="post" action=".">
-    <p>
-        <label for="id_name">Name:</label> {{ form.name }}
-        {% if form.name.errors %}*** {{ form.name.errors|join:", " }}{% endif %}
-    </p>
-    <p>
-        <label for="id_address">Address:</label> {{ form.address }}
-        {% if form.address.errors %}*** {{ form.address.errors|join:", " }}{% endif %}
-    </p>
-    <p>
-        <label for="id_city">City:</label> {{ form.city }}
-        {% if form.city.errors %}*** {{ form.city.errors|join:", " }}{% endif %}
-    </p>
-    <p>
-        <label for="id_state">State:</label> {{ form.state }}
-        {% if form.state.errors %}*** {{ form.state.errors|join:", " }}{% endif %}
-    </p>
-    <p>
-        <label for="id_zip_code">Zip:</label> {{ form.zip_code }}
-        {% if form.zip_code.errors %}*** {{ form.zip_code.errors|join:", " }}{% endif %}
-    </p>
-    <p>
-        <label for="id_place_type">Place type:</label> {{ form.place_type }}
-        {% if form.place_type.errors %}*** {{ form.place_type.errors|join:", " }}{% endif %}
-    </p>
-    <input type="submit" />
-    </form>
-    {% endblock %}
-
-The second two arguments to ``FormWrapper`` (``new_data`` and ``errors``)
-deserve some mention.
-
-The first is any "default" data to be used as values for the fields. Pulling
-the data from ``request.POST``, as is done above, makes sure that if there are
-errors, the values the user put in aren't lost. If you try the above example,
-you'll see this in action.
-
-The second argument is the error list retrieved from
-``manipulator.get_validation_errors``.  When passed into the ``FormWrapper``,
-this gives each field an ``errors`` item (which is a list of error messages
-associated with the field) as well as a ``html_error_list`` item, which is a
-``<ul>`` of error messages. The above template uses these error items to
-display a simple error message next to each field. The error list is saved as
-an ``error_dict`` attribute of the ``FormWrapper`` object.
-
-Using the ``ChangeManipulator``
--------------------------------
-
-The above has covered using the ``AddManipulator`` to create a new object. What
-about editing an existing one? It's shockingly similar to creating a new one::
-
-    def edit_place(request, place_id):
-        # Get the place in question from the database and create a
-        # ChangeManipulator at the same time.
-        try:
-            manipulator = Place.ChangeManipulator(place_id)
-        except Place.DoesNotExist:
-            raise Http404
-
-        # Grab the Place object in question for future use.
-        place = manipulator.original_object
-
-        if request.method == 'POST':
-            new_data = request.POST.copy()
-            errors = manipulator.get_validation_errors(new_data)
-            manipulator.do_html2python(new_data)
-            if not errors:
-                manipulator.save(new_data)
-
-                # Do a post-after-redirect so that reload works, etc.
-                return HttpResponseRedirect("/places/edit/%i/" % place.id)
-        else:
-            errors = {}
-            # This makes sure the form accurate represents the fields of the place.
-            new_data = manipulator.flatten_data()
-
-        form = forms.FormWrapper(manipulator, new_data, errors)
-        return render_to_response('places/edit_form.html', {'form': form, 'place': place})
-
-The only real differences are:
-
-    * We create a ``ChangeManipulator`` instead of an ``AddManipulator``.
-      The argument to a ``ChangeManipulator`` is the ID of the object
-      to be changed. As you can see, the initializer will raise an
-      ``ObjectDoesNotExist`` exception if the ID is invalid.
-
-    * ``ChangeManipulator.original_object`` stores the instance of the
-      object being edited.
-
-    * We set ``new_data`` based upon ``flatten_data()`` from the manipulator.
-      ``flatten_data()`` takes the data from the original object under
-      manipulation, and converts it into a data dictionary that can be used
-      to populate form elements with the existing values for the object.
-
-    * The above example uses a different template, so create and edit can be
-      "skinned" differently if needed, but the form chunk itself is completely
-      identical to the one in the create form above.
-
-The astute programmer will notice the add and create functions are nearly
-identical and could in fact be collapsed into a single view. This is left as an
-exercise for said programmer.
-
-(However, the even-more-astute programmer will take heed of the note at the top
-of this document and check out the :ref:`generic views <ref-generic-views>`
-documentation if all she wishes to do is this type of simple create/update.)
-
-Custom forms and manipulators
-=============================
-
-All the above is fine and dandy if you just want to use the automatically
-created manipulators. But the coolness doesn't end there: You can easily create
-your own custom manipulators for handling custom forms.
-
-Custom manipulators are pretty simple. Here's a manipulator that you might use
-for a "contact" form on a website::
-
-    from django import oldforms as forms
-
-    urgency_choices = (
-        (1, "Extremely urgent"),
-        (2, "Urgent"),
-        (3, "Normal"),
-        (4, "Unimportant"),
-    )
-
-    class ContactManipulator(forms.Manipulator):
-        def __init__(self):
-            self.fields = (
-                forms.EmailField(field_name="from", is_required=True),
-                forms.TextField(field_name="subject", length=30, max_length=200, is_required=True),
-                forms.SelectField(field_name="urgency", choices=urgency_choices),
-                forms.LargeTextField(field_name="contents", is_required=True),
-            )
-
-A certain similarity to Django's models should be apparent. The only required
-method of a custom manipulator is ``__init__`` which must define the fields
-present in the manipulator.  See the ``django.forms`` module for
-all the form fields provided by Django.
-
-You use this custom manipulator exactly as you would use an auto-generated one.
-Here's a simple function that might drive the above form::
-
-    def contact_form(request):
-        manipulator = ContactManipulator()
-        if request.method == 'POST':
-            new_data = request.POST.copy()
-            errors = manipulator.get_validation_errors(new_data)
-            manipulator.do_html2python(new_data)
-            if not errors:
-
-                # Send e-mail using new_data here...
-
-                return HttpResponseRedirect("/contact/thankyou/")
-        else:
-            errors = new_data = {}
-        form = forms.FormWrapper(manipulator, new_data, errors)
-        return render_to_response('contact_form.html', {'form': form})
-
-Implementing ``flatten_data`` for custom manipulators
-------------------------------------------------------
-
-It is possible (although rarely needed) to replace the default automatically
-created manipulators on a model with your own custom manipulators. If you do
-this and you are intending to use those models in generic views, you should
-also define a ``flatten_data`` method in any ``ChangeManipulator`` replacement.
-This should act like the default ``flatten_data`` and return a dictionary
-mapping field names to their values, like so::
-
-    def flatten_data(self):
-        obj = self.original_object
-        return dict(
-            from = obj.from,
-            subject = obj.subject,
-            ...
-        )
-
-In this way, your new change manipulator will act exactly like the default
-version.
-
-``FileField`` and ``ImageField`` special cases
-==============================================
-
-Dealing with ``FileField`` and ``ImageField`` objects is a little more
-complicated.
-
-First, you'll need to make sure that your ``<form>`` element correctly defines
-the ``enctype`` as ``"multipart/form-data"``, in order to upload files::
-
-  <form enctype="multipart/form-data" method="post" action="/foo/">
-
-Next, you'll need to treat the field in the template slightly differently. A
-``FileField`` or ``ImageField`` is represented by *two* HTML form elements.
-
-For example, given this field in a model::
-
-   photo = model.ImageField('/path/to/upload/location')
-
-You'd need to display two formfields in the template::
-
-   <p><label for="id_photo">Photo:</label> {{ form.photo }}{{ form.photo_file }}</p>
-
-The first bit (``{{ form.photo }}``) displays the currently-selected file,
-while the second (``{{ form.photo_file }}``) actually contains the file upload
-form field. Thus, at the validation layer you need to check the ``photo_file``
-key.
-
-Finally, in your view, make sure to access ``request.FILES``, rather than
-``request.POST``, for the uploaded files. This is necessary because
-``request.POST`` does not contain file-upload data.
-
-For example, following the ``new_data`` convention, you might do something like
-this::
-
-   new_data = request.POST.copy()
-   new_data.update(request.FILES)
-
-Validators
-==========
-
-One useful feature of manipulators is the automatic validation. Validation is
-done using a simple validation API: A validator is a callable that raises a
-``ValidationError`` if there's something wrong with the data.
-``django.core.validators`` defines a host of validator functions (see below),
-but defining your own couldn't be easier::
-
-    from django.core import validators
-    from django import oldforms as forms
-
-    class ContactManipulator(forms.Manipulator):
-        def __init__(self):
-            self.fields = (
-                # ... snip fields as above ...
-                forms.EmailField(field_name="to", validator_list=[self.isValidToAddress])
-            )
-
-        def isValidToAddress(self, field_data, all_data):
-            if not field_data.endswith("@example.com"):
-                raise validators.ValidationError("You can only send messages to example.com e-mail addresses.")
-
-Above, we've added a "to" field to the contact form, but required that the "to"
-address end with "@example.com" by adding the ``isValidToAddress`` validator to
-the field's ``validator_list``.
-
-The arguments to a validator function take a little explanation.  ``field_data``
-is the value of the field in question, and ``all_data`` is a dictionary of all
-the data being validated.
-
-.. admonition:: Note::
-
-    At the point validators are called all data will still be
-    strings (as ``do_html2python`` hasn't been called yet).
-
-Also, because consistency in user interfaces is important, we strongly urge you
-to put punctuation at the end of your validation messages.
-
-When are validators called?
----------------------------
-
-After a form has been submitted, Django validates each field in turn. First,
-if the field is required, Django checks that it is present and non-empty. Then,
-if that test passes *and the form submission contained data* for that field, all
-the validators for that field are called in turn. The emphasized portion in the
-last sentence is important: if a form field is not submitted (because it
-contains no data -- which is normal HTML behavior), the validators are not
-run against the field.
-
-This feature is particularly important for models using
-``models.BooleanField`` or custom manipulators using things like
-``forms.CheckBoxField``. If the checkbox is not selected, it will not
-contribute to the form submission.
-
-If you would like your validator to run *always*, regardless of whether its
-attached field contains any data, set the ``always_test`` attribute on the
-validator function. For example::
-
-    def my_custom_validator(field_data, all_data):
-        # ...
-    my_custom_validator.always_test = True
-
-This validator will always be executed for any field it is attached to.
-
-Ready-made validators
----------------------
-
-Writing your own validator is not difficult, but there are some situations
-that come up over and over again. Django comes with a number of validators
-that can be used directly in your code. All of these functions and classes
-reside in ``django/core/validators.py``.
-
-The following validators should all be self-explanatory. Each one provides a
-check for the given property:
-
-    * isAlphaNumeric
-    * isAlphaNumericURL
-    * isSlug
-    * isLowerCase
-    * isUpperCase
-    * isCommaSeparatedIntegerList
-    * isCommaSeparatedEmailList
-    * isValidIPAddress4
-    * isNotEmpty
-    * isOnlyDigits
-    * isNotOnlyDigits
-    * isInteger
-    * isOnlyLetters
-    * isValidANSIDate
-    * isValidANSITime
-    * isValidEmail
-    * isValidFloat
-    * isValidImage
-    * isValidImageURL
-    * isValidPhone
-    * isValidQuicktimeVideoURL
-    * isValidURL
-    * isValidHTML
-    * isWellFormedXml
-    * isWellFormedXmlFragment
-    * isExistingURL
-    * isValidUSState
-    * hasNoProfanities
-
-There are also a group of validators that are slightly more flexible. For
-these validators, you create a validator instance, passing in the parameters
-described below. The returned object is a callable that can be used as a
-validator.
-
-For example::
-
-    from django.core import validators
-    from django import oldforms as forms
-
-    power_validator = validators.IsAPowerOf(2)
-
-    class InstallationManipulator(forms.Manipulator)
-        def __init__(self):
-            self.fields = (
-                ...
-                forms.IntegerField(field_name = "size", validator_list=[power_validator])
-            )
-
-Here, ``validators.IsAPowerOf(...)`` returned something that could be used as
-a validator (in this case, a check that a number was a power of 2).
-
-Each of the standard validators that take parameters have an optional final
-argument (``error_message``) that is the message returned when validation
-fails. If no message is passed in, a default message is used.
-
-``AlwaysMatchesOtherField``
-    Takes a field name and the current field is valid if and only if its value
-    matches the contents of the other field.
-
-``ValidateIfOtherFieldEquals``
-    Takes three parameters: ``other_field``, ``other_value`` and
-    ``validator_list``, in that order. If ``other_field`` has a value of
-    ``other_value``, then the validators in ``validator_list`` are all run
-    against the current field.
-
-``RequiredIfOtherFieldGiven``
-    Takes a field name of the current field is only required if the other
-    field has a value.
-
-``RequiredIfOtherFieldsGiven``
-    Similar to ``RequiredIfOtherFieldGiven``, except that it takes a list of
-    field names and if any one of the supplied fields has a value provided,
-    the current field being validated is required.
-
-``RequiredIfOtherFieldNotGiven``
-    Takes the name of the other field and this field is only required if the
-    other field has no value.
-
-``RequiredIfOtherFieldEquals`` and ``RequiredIfOtherFieldDoesNotEqual``
-    Each of these validator classes takes a field name and a value (in that
-    order). If the given field does (or does not have, in the latter case) the
-    given value, then the current field being validated is required.
-
-    An optional ``other_label`` argument can be passed which, if given, is used
-    in error messages instead of the value. This allows more user friendly error
-    messages if the value itself is not descriptive enough.
-
-    Note that because validators are called before any ``do_html2python()``
-    functions, the value being compared against is a string. So
-    ``RequiredIfOtherFieldEquals('choice', '1')`` is correct, whilst
-    ``RequiredIfOtherFieldEquals('choice', 1)`` will never result in the
-    equality test succeeding.
-
-``IsLessThanOtherField``
-    Takes a field name and validates that the current field being validated
-    has a value that is less than (or equal to) the other field's value.
-    Again, comparisons are done using strings, so be cautious about using
-    this function to compare data that should be treated as another type. The
-    string "123" is less than the string "2", for example. If you don't want
-    string comparison here, you will need to write your own validator.
-
-``NumberIsInRange``
-    Takes two boundary numbers, ``lower`` and ``upper``, and checks that the
-    field is greater than ``lower`` (if given) and less than ``upper`` (if
-    given).
-
-    Both checks are inclusive. That is, ``NumberIsInRange(10, 20)`` will allow
-    values of both 10 and 20. This validator only checks numeric values
-    (e.g., float and integer values).
-
-``IsAPowerOf``
-    Takes an integer argument and when called as a validator, checks that the
-    field being validated is a power of the integer.
-
-``IsValidDecimal``
-    Takes a maximum number of digits and number of decimal places (in that
-    order) and validates whether the field is a decimal with no more than the
-    maximum number of digits and decimal places.
-
-``MatchesRegularExpression``
-    Takes a regular expression (a string) as a parameter and validates the
-    field value against it.
-
-``AnyValidator``
-    Takes a list of validators as a parameter. At validation time, if the
-    field successfully validates against any one of the validators, it passes
-    validation. The validators are tested in the order specified in the
-    original list.
-
-``URLMimeTypeCheck``
-    Used to validate URL fields. Takes a list of MIME types (such as
-    ``text/plain``) at creation time. At validation time, it verifies that the
-    field is indeed a URL and then tries to retrieve the content at the URL.
-    Validation succeeds if the content could be retrieved and it has a content
-    type from the list used to create the validator.
-
-``RelaxNGCompact``
-    Used to validate an XML document against a Relax NG compact schema. Takes a
-    file path to the location of the schema and an optional root element (which
-    is wrapped around the XML fragment before validation, if supplied). At
-    validation time, the XML fragment is validated against the schema using the
-    executable specified in the ``JING_PATH`` setting (see the :ref:`settings
-    <ref-settings>` document for more details).

=== removed file 'docs/obsolete/newforms-migration.txt'
--- docs/obsolete/newforms-migration.txt	2008-08-23 22:25:40 +0000
+++ docs/obsolete/newforms-migration.txt	1970-01-01 00:00:00 +0000
@@ -1,48 +0,0 @@
-.. _howto-newforms-migration:
-
-Migrating from "oldforms" to "newforms"
-=======================================
-
-:mod:`django.newforms` is new in Django's 0.96 release, but, as it won't be new
-forever. We plan to rename it to ``django.forms`` in next official release. The
-current ``django.forms`` package will be available as ``django.oldforms`` until
-Django 1.0, when we plan to remove it for good.
-
-If you're using "old" forms -- and if you started using Django after 0.96 you're
-probably not -- you need to read this document and understand this migration
-plan.
-
-    * The old forms framework (the current ``django.forms``) has been copied to
-      ``django.oldforms``. Thus, you can start upgrading your code *now*,
-      rather than waiting for the future backwards-incompatible change, by
-      changing your import statements like this::
-
-          from django import forms             # old
-          from django import oldforms as forms # new
-
-    * In the next Django release, we will move the current ``django.newforms``
-      to ``django.forms``. This will be a backwards-incompatible change, and
-      anybody who is still using the old version of ``django.forms`` at that
-      time will need to change their import statements, as described in the
-      previous bullet.
-
-    * We will remove ``django.oldforms`` in Django 1.0. It will continue to be
-      available from older tags in our SVN repository, but it will not be
-      consider part of Django, and will not be supported..
-
-With this in mind, we recommend you use the following import statement when
-using ``django.newforms``::
-
-    from django import newforms as forms
-
-This way, your code can refer to the ``forms`` module, and when
-``django.newforms`` is renamed to ``django.forms``, you'll only have to change
-your ``import`` statements.
-
-If you prefer "``import *``" syntax, you can do the following::
-
-    from django.newforms import *
-
-This will import all fields, widgets, form classes and other various utilities
-into your local namespace. Some people find this convenient; others find it
-too messy. The choice is yours.

=== modified file 'docs/ref/models/fields.txt'
--- docs/ref/models/fields.txt	2008-08-26 01:59:25 +0000
+++ docs/ref/models/fields.txt	2008-08-26 05:02:24 +0000
@@ -287,15 +287,6 @@
 
 Like :attr:`~Field.unique_for_date` and :attr:`~Field.unique_for_month`.
 
-``validator_list``
-------------------
-
-.. attribute:: Field.validator_list
-
-A list of extra validators to apply to the field. Each should be a callable that
-takes the parameters ``field_data, all_data`` and raises
-:exc:`django.core.validators.ValidationError` for errors.
-
 .. _model-field-types:
 
 Field types

=== modified file 'docs/topics/forms/modelforms.txt'
--- docs/topics/forms/modelforms.txt	2008-08-23 22:25:40 +0000
+++ docs/topics/forms/modelforms.txt	2008-08-26 05:02:24 +0000
@@ -67,8 +67,7 @@
                                      (from ``django.contrib.localflavor.us``)
     ``PositiveIntegerField``         ``IntegerField``
     ``PositiveSmallIntegerField``    ``IntegerField``
-    ``SlugField``                    ``RegexField`` accepting only letters,
-                                     numbers, underscores and hyphens
+    ``SlugField``                    ``SlugField``
     ``SmallIntegerField``            ``IntegerField``
     ``TextField``                    ``CharField`` with ``widget=Textarea``
     ``TimeField``                    ``TimeField``

=== modified file 'docs/topics/testing.txt'
--- docs/topics/testing.txt	2008-08-26 00:52:55 +0000
+++ docs/topics/testing.txt	2008-08-26 05:02:24 +0000
@@ -899,8 +899,7 @@
     rendered on the form.
 
     ``form`` is the name the ``Form`` instance was given in the template
-    context. Note that this works only for ``forms.Form`` instances, not
-    ``oldforms.Form`` instances.
+    context.
 
     ``field`` is the name of the field on the form to check. If ``field``
     has a value of ``None``, non-field errors (errors you can access via

=== modified file 'tests/modeltests/field_subclassing/models.py'
--- tests/modeltests/field_subclassing/models.py	2008-04-27 02:50:16 +0000
+++ tests/modeltests/field_subclassing/models.py	2008-08-26 05:02:24 +0000
@@ -53,9 +53,6 @@
             return []
         raise FieldError('Invalid lookup type: %r' % lookup_type)
 
-    def flatten_data(self, follow, obj=None):
-        return {self.attname: force_unicode(self._get_val_from_obj(obj))}
-
 class MyModel(models.Model):
     name = models.CharField(max_length=10)
     data = SmallField('small field')

=== removed directory 'tests/modeltests/manipulators'
=== removed file 'tests/modeltests/manipulators/__init__.py'
=== removed file 'tests/modeltests/manipulators/models.py'
--- tests/modeltests/manipulators/models.py	2008-08-12 14:15:38 +0000
+++ tests/modeltests/manipulators/models.py	1970-01-01 00:00:00 +0000
@@ -1,105 +0,0 @@
-# coding: utf-8
-"""
-27. Default manipulators
-
-Each model gets an ``AddManipulator`` and ``ChangeManipulator`` by default.
-"""
-
-from django.db import models
-
-class Musician(models.Model):
-    first_name = models.CharField(max_length=30)
-    last_name = models.CharField(max_length=30)
-
-    def __unicode__(self):
-        return u"%s %s" % (self.first_name, self.last_name)
-
-class Album(models.Model):
-    name = models.CharField(max_length=100)
-    musician = models.ForeignKey(Musician)
-    release_date = models.DateField(blank=True, null=True)
-
-    def __unicode__(self):
-        return self.name
-
-__test__ = {'API_TESTS':u"""
->>> from django.utils.datastructures import MultiValueDict
-
-# Create a Musician object via the default AddManipulator.
->>> man = Musician.AddManipulator()
->>> data = MultiValueDict({'first_name': ['Ella'], 'last_name': ['Fitzgerald']})
-
->>> man.get_validation_errors(data)
-{}
->>> man.do_html2python(data)
->>> m1 = man.save(data)
-
-# Verify it worked.
->>> Musician.objects.all()
-[<Musician: Ella Fitzgerald>]
->>> [m1] == list(Musician.objects.all())
-True
-
-# Attempt to add a Musician without a first_name.
->>> man.get_validation_errors(MultiValueDict({'last_name': ['Blakey']}))['first_name']
-[u'This field is required.']
-
-# Attempt to add a Musician without a first_name and last_name.
->>> errors = man.get_validation_errors(MultiValueDict({}))
->>> errors['first_name']
-[u'This field is required.']
->>> errors['last_name']
-[u'This field is required.']
-
-# Attempt to create an Album without a name or musician.
->>> man = Album.AddManipulator()
->>> errors = man.get_validation_errors(MultiValueDict({}))
->>> errors['musician']
-[u'This field is required.']
->>> errors['name']
-[u'This field is required.']
-
-# Attempt to create an Album with an invalid musician.
->>> errors = man.get_validation_errors(MultiValueDict({'name': ['Sallies Fforth'], 'musician': ['foo']}))
->>> errors['musician']
-[u"Select a valid choice; 'foo' is not in [u'', u'1']."]
-
-# Attempt to create an Album with an invalid release_date.
->>> errors = man.get_validation_errors(MultiValueDict({'name': ['Sallies Fforth'], 'musician': ['1'], 'release_date': 'today'}))
->>> errors['release_date']
-[u'Enter a valid date in YYYY-MM-DD format.']
-
-# Create an Album without a release_date (because it's optional).
->>> data = MultiValueDict({'name': ['Ella and Basie'], 'musician': ['1']})
->>> man.get_validation_errors(data)
-{}
->>> man.do_html2python(data)
->>> a1 = man.save(data)
-
-# Verify it worked.
->>> Album.objects.all()
-[<Album: Ella and Basie>]
->>> Album.objects.get().musician
-<Musician: Ella Fitzgerald>
-
-# Create an Album with a release_date.
->>> data = MultiValueDict({'name': ['Ultimate Ella'], 'musician': ['1'], 'release_date': ['2005-02-13']})
->>> man.get_validation_errors(data)
-{}
->>> man.do_html2python(data)
->>> a2 = man.save(data)
-
-# Verify it worked.
->>> Album.objects.order_by('name')
-[<Album: Ella and Basie>, <Album: Ultimate Ella>]
->>> a2 = Album.objects.get(pk=2)
->>> a2
-<Album: Ultimate Ella>
->>> a2.release_date
-datetime.date(2005, 2, 13)
-
-# Test isValidFloat Unicode coercion
->>> from django.core.validators import isValidFloat, ValidationError
->>> try: isValidFloat(u"ä", None)
-... except ValidationError: pass
-"""}

