Anonymous avatar Anonymous committed ad3ded9

Removed oldforms, validators, and related code:
* Removed `Manipulator`, `AutomaticManipulator`, and related classes.
* Removed oldforms specific bits from model fields:
* Removed `validator_list` and `core` arguments from constructors.
* Removed the methods:
* `get_manipulator_field_names`
* `get_manipulator_field_objs`
* `get_manipulator_fields`
* `get_manipulator_new_data`
* `prepare_field_objs_and_params`
* `get_follow`
* Renamed `flatten_data` method to `value_to_string` for better alignment with its use by the serialization framework, which was the only remaining code using `flatten_data`.
* Removed oldforms methods from `django.db.models.Options` class: `get_followed_related_objects`, `get_data_holders`, `get_follow`, and `has_field_type`.
* Removed oldforms-admin specific options from `django.db.models.fields.related` classes: `num_in_admin`, `min_num_in_admin`, `max_num_in_admin`, `num_extra_on_change`, and `edit_inline`.
* Serialization framework
* `Serializer.get_string_value` now calls the model fields' renamed `value_to_string` methods.
* Removed a special-casing of `models.DateTimeField` in `core.serializers.base.Serializer.get_string_value` that's handled by `django.db.models.fields.DateTimeField.value_to_string`.
* Removed `django.core.validators`:
* Moved `ValidationError` exception to `django.core.exceptions`.
* For the couple places that were using validators, brought over the necessary code to maintain the same functionality.
* Introduced a SlugField form field for validation and to compliment the SlugField model field (refs #8040).
* Removed an oldforms-style model creation hack (refs #2160).

Comments (0)

Files changed (35)

django/contrib/admin/util.py

                         perms_needed.add(related.opts.verbose_name)
                         # We don't care about populating deleted_objects now.
                         continue
-                if related.field.rel.edit_inline or not has_admin:
+                if not has_admin:
                     # Don't display link to edit, because it either has no
                     # admin or is edited inline.
                     nh(deleted_objects, current_depth, [u'%s: %s' % (force_unicode(capfirst(related.opts.verbose_name)), sub_obj), []])
             has_related_objs = False
             for sub_obj in getattr(obj, rel_opts_name).all():
                 has_related_objs = True
-                if related.field.rel.edit_inline or not has_admin:
+                if not has_admin:
                     # Don't display link to edit, because it either has no
                     # admin or is edited inline.
                     nh(deleted_objects, current_depth, [u'%s: %s' % (force_unicode(capfirst(related.opts.verbose_name)), sub_obj), []])
 
         if has_related_objs:
             for sub_obj in rel_objs.all():
-                if related.field.rel.edit_inline or not has_admin:
+                if not has_admin:
                     # Don't display link to edit, because it either has no
                     # admin or is edited inline.
                     nh(deleted_objects, current_depth, [_('One or more %(fieldname)s in %(name)s: %(obj)s') % \

django/contrib/auth/management/commands/createsuperuser.py

 import sys
 from optparse import make_option
 from django.contrib.auth.models import User
-from django.core import validators
+from django.core import exceptions
 from django.core.management.base import BaseCommand, CommandError
+from django.utils.translation import ugettext as _
 
 RE_VALID_USERNAME = re.compile('\w+$')
+EMAIL_RE = re.compile(
+    r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"  # dot-atom
+    r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"' # quoted-string
+    r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE)  # domain
+
+def is_valid_email(value):
+    if not EMAIL_RE.search(value):
+        raise exceptions.ValidationError(_('Enter a valid e-mail address.'))
 
 class Command(BaseCommand):
     option_list = BaseCommand.option_list + (
             if not RE_VALID_USERNAME.match(username):
                 raise CommandError("Invalid username. Use only letters, digits, and underscores")
             try:
-                validators.isValidEmail(email, None)
-            except validators.ValidationError:
+                is_valid_email(email)
+            except exceptions.ValidationError:
                 raise CommandError("Invalid email address.")
 
         password = ''
                     if not email:
                         email = raw_input('E-mail address: ')
                     try:
-                        validators.isValidEmail(email, None)
-                    except validators.ValidationError:
+                        is_valid_email(email)
+                    except exceptions.ValidationError:
                         sys.stderr.write("Error: That e-mail address is invalid.\n")
                         email = None
                     else:

django/contrib/auth/models.py

 from django.contrib import auth
-from django.core import validators
 from django.core.exceptions import ImproperlyConfigured
 from django.db import models
 from django.db.models.manager import EmptyManager

django/contrib/comments/forms.py

         """
         comment = self.cleaned_data["comment"]
         if settings.COMMENTS_ALLOW_PROFANITIES == False:
-            # Logic adapted from django.core.validators; it's not clear if they
-            # should be used in newforms or will be deprecated along with the
-            # rest of oldforms
             bad_words = [w for w in settings.PROFANITIES_LIST if w in comment.lower()]
             if bad_words:
                 plural = len(bad_words) > 1

django/contrib/comments/models.py

 from django.contrib.contenttypes.models import ContentType
 from django.contrib.sites.models import Site
 from django.db import models
-from django.core import urlresolvers, validators
+from django.core import urlresolvers
 from django.utils.translation import ugettext_lazy as _
 from django.conf import settings
 

django/contrib/contenttypes/generic.py

 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):
     """
         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 value_to_string(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
         self.to = to
         self.related_name = related_name
         self.limit_choices_to = limit_choices_to or {}
-        self.edit_inline = False
         self.symmetrical = symmetrical
         self.multiple = True
 
     """
     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
 
 class GenericTabularInline(GenericInlineModelAdmin):
     template = 'admin/edit_inline/tabular.html'
-

django/contrib/flatpages/models.py

-from django.core import validators
 from django.db import models
 from django.contrib.sites.models import Site
 from django.utils.translation import ugettext_lazy as _

django/contrib/localflavor/jp/forms.py

 JP-specific Form helpers
 """
 
-from django.core import validators
 from django.forms import ValidationError
 from django.utils.translation import ugettext_lazy as _
 from django.forms.fields import RegexField, Select

django/core/exceptions.py

     """Some kind of problem with a model field."""
     pass
 
+class ValidationError(Exception):
+    """An error while validating data."""
+    pass

django/core/serializers/base.py

         """
         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.value_to_string(obj))
 
     def start_serialization(self):
         """

django/core/validators.py

-"""
-A library of validators that return None and raise ValidationError when the
-provided data isn't valid.
-
-Validators may be callable classes, and they may have an 'always_test'
-attribute. If an 'always_test' attribute exists (regardless of value), the
-validator will *always* be run, regardless of whether its associated
-form field is required.
-"""
-
-import urllib2
-import re
-try:
-    from decimal import Decimal, DecimalException
-except ImportError:
-    from django.utils._decimal import Decimal, DecimalException    # Python 2.3
-
-from django.conf import settings
-from django.utils.translation import ugettext as _, ugettext_lazy, ungettext
-from django.utils.functional import Promise, lazy
-from django.utils.encoding import force_unicode, smart_str
-
-_datere = r'\d{4}-\d{1,2}-\d{1,2}'
-_timere = r'(?:[01]?[0-9]|2[0-3]):[0-5][0-9](?::[0-5][0-9])?'
-alnum_re = re.compile(r'^\w+$')
-alnumurl_re = re.compile(r'^[-\w/]+$')
-ansi_date_re = re.compile('^%s$' % _datere)
-ansi_time_re = re.compile('^%s$' % _timere)
-ansi_datetime_re = re.compile('^%s %s$' % (_datere, _timere))
-email_re = re.compile(
-    r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"  # dot-atom
-    r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"' # quoted-string
-    r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE)  # domain
-integer_re = re.compile(r'^-?\d+$')
-ip4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$')
-phone_re = re.compile(r'^[A-PR-Y0-9]{3}-[A-PR-Y0-9]{3}-[A-PR-Y0-9]{4}$', re.IGNORECASE)
-slug_re = re.compile(r'^[-\w]+$')
-url_re = re.compile(r'^https?://\S+$')
-
-lazy_inter = lazy(lambda a,b: force_unicode(a) % b, unicode)
-
-class ValidationError(Exception):
-    def __init__(self, message):
-        "ValidationError can be passed a string or a list."
-        if isinstance(message, list):
-            self.messages = [force_unicode(msg) for msg in message]
-        else:
-            assert isinstance(message, (basestring, Promise)), ("%s should be a string" % repr(message))
-            self.messages = [force_unicode(message)]
-
-    def __str__(self):
-        # This is needed because, without a __str__(), printing an exception
-        # instance would result in this:
-        # AttributeError: ValidationError instance has no attribute 'args'
-        # See http://www.python.org/doc/current/tut/node10.html#handling
-        return str(self.messages)
-
-class CriticalValidationError(Exception):
-    def __init__(self, message):
-        "ValidationError can be passed a string or a list."
-        if isinstance(message, list):
-            self.messages = [force_unicode(msg) for msg in message]
-        else:
-            assert isinstance(message, (basestring, Promise)), ("'%s' should be a string" % message)
-            self.messages = [force_unicode(message)]
-
-    def __str__(self):
-        return str(self.messages)
-
-def isAlphaNumeric(field_data, all_data):
-    if not alnum_re.search(field_data):
-        raise ValidationError, _("This value must contain only letters, numbers and underscores.")
-
-def isAlphaNumericURL(field_data, all_data):
-    if not alnumurl_re.search(field_data):
-        raise ValidationError, _("This value must contain only letters, numbers, underscores, dashes or slashes.")
-
-def isSlug(field_data, all_data):
-    if not slug_re.search(field_data):
-        raise ValidationError, _("This value must contain only letters, numbers, underscores or hyphens.")
-
-def isLowerCase(field_data, all_data):
-    if field_data.lower() != field_data:
-        raise ValidationError, _("Uppercase letters are not allowed here.")
-
-def isUpperCase(field_data, all_data):
-    if field_data.upper() != field_data:
-        raise ValidationError, _("Lowercase letters are not allowed here.")
-
-def isCommaSeparatedIntegerList(field_data, all_data):
-    for supposed_int in field_data.split(','):
-        try:
-            int(supposed_int)
-        except ValueError:
-            raise ValidationError, _("Enter only digits separated by commas.")
-
-def isCommaSeparatedEmailList(field_data, all_data):
-    """
-    Checks that field_data is a string of e-mail addresses separated by commas.
-    Blank field_data values will not throw a validation error, and whitespace
-    is allowed around the commas.
-    """
-    for supposed_email in field_data.split(','):
-        try:
-            isValidEmail(supposed_email.strip(), '')
-        except ValidationError:
-            raise ValidationError, _("Enter valid e-mail addresses separated by commas.")
-
-def isValidIPAddress4(field_data, all_data):
-    if not ip4_re.search(field_data):
-        raise ValidationError, _("Please enter a valid IP address.")
-
-def isNotEmpty(field_data, all_data):
-    if field_data.strip() == '':
-        raise ValidationError, _("Empty values are not allowed here.")
-
-def isOnlyDigits(field_data, all_data):
-    if not field_data.isdigit():
-        raise ValidationError, _("Non-numeric characters aren't allowed here.")
-
-def isNotOnlyDigits(field_data, all_data):
-    if field_data.isdigit():
-        raise ValidationError, _("This value can't be comprised solely of digits.")
-
-def isInteger(field_data, all_data):
-    # This differs from isOnlyDigits because this accepts the negative sign
-    if not integer_re.search(field_data):
-        raise ValidationError, _("Enter a whole number.")
-
-def isOnlyLetters(field_data, all_data):
-    if not field_data.isalpha():
-        raise ValidationError, _("Only alphabetical characters are allowed here.")
-
-def _isValidDate(date_string):
-    """
-    A helper function used by isValidANSIDate and isValidANSIDatetime to
-    check if the date is valid.  The date string is assumed to already be in
-    YYYY-MM-DD format.
-    """
-    from datetime import date
-    # Could use time.strptime here and catch errors, but datetime.date below
-    # produces much friendlier error messages.
-    year, month, day = map(int, date_string.split('-'))
-    try:
-        date(year, month, day)
-    except ValueError, e:
-        msg = _('Invalid date: %s') % _(str(e))
-        raise ValidationError, msg
-
-def isValidANSIDate(field_data, all_data):
-    if not ansi_date_re.search(field_data):
-        raise ValidationError, _('Enter a valid date in YYYY-MM-DD format.')
-    _isValidDate(field_data)
-
-def isValidANSITime(field_data, all_data):
-    if not ansi_time_re.search(field_data):
-        raise ValidationError, _('Enter a valid time in HH:MM format.')
-
-def isValidANSIDatetime(field_data, all_data):
-    if not ansi_datetime_re.search(field_data):
-        raise ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM format.')
-    _isValidDate(field_data.split()[0])
-
-def isValidEmail(field_data, all_data):
-    if not email_re.search(field_data):
-        raise ValidationError, _('Enter a valid e-mail address.')
-
-def isValidImage(field_data, all_data):
-    """
-    Checks that the file-upload field data contains a valid image (GIF, JPG,
-    PNG, possibly others -- whatever the Python Imaging Library supports).
-    """
-    from PIL import Image
-    from cStringIO import StringIO
-    try:
-        content = field_data.read()
-    except TypeError:
-        raise ValidationError, _("No file was submitted. Check the encoding type on the form.")
-    try:
-        # load() is the only method that can spot a truncated JPEG,
-        #  but it cannot be called sanely after verify()
-        trial_image = Image.open(StringIO(content))
-        trial_image.load()
-        # verify() is the only method that can spot a corrupt PNG,
-        #  but it must be called immediately after the constructor
-        trial_image = Image.open(StringIO(content))
-        trial_image.verify()
-    except Exception: # Python Imaging Library doesn't recognize it as an image
-        raise ValidationError, _("Upload a valid image. The file you uploaded was either not an image or a corrupted image.")
-
-def isValidImageURL(field_data, all_data):
-    uc = URLMimeTypeCheck(('image/jpeg', 'image/gif', 'image/png'))
-    try:
-        uc(field_data, all_data)
-    except URLMimeTypeCheck.InvalidContentType:
-        raise ValidationError, _("The URL %s does not point to a valid image.") % field_data
-
-def isValidPhone(field_data, all_data):
-    if not phone_re.search(field_data):
-        raise ValidationError, _('Phone numbers must be in XXX-XXX-XXXX format. "%s" is invalid.') % field_data
-
-def isValidQuicktimeVideoURL(field_data, all_data):
-    "Checks that the given URL is a video that can be played by QuickTime (qt, mpeg)"
-    uc = URLMimeTypeCheck(('video/quicktime', 'video/mpeg',))
-    try:
-        uc(field_data, all_data)
-    except URLMimeTypeCheck.InvalidContentType:
-        raise ValidationError, _("The URL %s does not point to a valid QuickTime video.") % field_data
-
-def isValidURL(field_data, all_data):
-    if not url_re.search(field_data):
-        raise ValidationError, _("A valid URL is required.")
-
-def isValidHTML(field_data, all_data):
-    import urllib, urllib2
-    try:
-        u = urllib2.urlopen('http://validator.w3.org/check', urllib.urlencode({'fragment': field_data, 'output': 'xml'}))
-    except:
-        # Validator or Internet connection is unavailable. Fail silently.
-        return
-    html_is_valid = (u.headers.get('x-w3c-validator-status', 'Invalid') == 'Valid')
-    if html_is_valid:
-        return
-    from xml.dom.minidom import parseString
-    error_messages = [e.firstChild.wholeText for e in parseString(u.read()).getElementsByTagName('messages')[0].getElementsByTagName('msg')]
-    raise ValidationError, _("Valid HTML is required. Specific errors are:\n%s") % "\n".join(error_messages)
-
-def isWellFormedXml(field_data, all_data):
-    from xml.dom.minidom import parseString
-    try:
-        parseString(field_data)
-    except Exception, e: # Naked except because we're not sure what will be thrown
-        raise ValidationError, _("Badly formed XML: %s") % str(e)
-
-def isWellFormedXmlFragment(field_data, all_data):
-    isWellFormedXml('<root>%s</root>' % field_data, all_data)
-
-def isExistingURL(field_data, all_data):
-    try:
-        headers = {
-            "Accept" : "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
-            "Accept-Language" : "en-us,en;q=0.5",
-            "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
-            "Connection" : "close",
-            "User-Agent": settings.URL_VALIDATOR_USER_AGENT
-            }
-        req = urllib2.Request(field_data,None, headers)
-        u = urllib2.urlopen(req)
-    except ValueError:
-        raise ValidationError, _("Invalid URL: %s") % field_data
-    except urllib2.HTTPError, e:
-        # 401s are valid; they just mean authorization is required.
-        # 301 and 302 are redirects; they just mean look somewhere else.
-        if str(e.code) not in ('401','301','302'):
-            raise ValidationError, _("The URL %s is a broken link.") % field_data
-    except: # urllib2.URLError, httplib.InvalidURL, etc.
-        raise ValidationError, _("The URL %s is a broken link.") % field_data
-
-def isValidUSState(field_data, all_data):
-    "Checks that the given string is a valid two-letter U.S. state abbreviation"
-    states = ['AA', 'AE', 'AK', 'AL', 'AP', 'AR', 'AS', 'AZ', 'CA', 'CO', 'CT', 'DC', 'DE', 'FL', 'FM', 'GA', 'GU', 'HI', 'IA', 'ID', 'IL', 'IN', 'KS', 'KY', 'LA', 'MA', 'MD', 'ME', 'MH', 'MI', 'MN', 'MO', 'MP', 'MS', 'MT', 'NC', 'ND', 'NE', 'NH', 'NJ', 'NM', 'NV', 'NY', 'OH', 'OK', 'OR', 'PA', 'PR', 'PW', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VA', 'VI', 'VT', 'WA', 'WI', 'WV', 'WY']
-    if field_data.upper() not in states:
-        raise ValidationError, _("Enter a valid U.S. state abbreviation.")
-
-def hasNoProfanities(field_data, all_data):
-    """
-    Checks that the given string has no profanities in it. This does a simple
-    check for whether each profanity exists within the string, so 'fuck' will
-    catch 'motherfucker' as well. Raises a ValidationError such as:
-        Watch your mouth! The words "f--k" and "s--t" are not allowed here.
-    """
-    field_data = field_data.lower() # normalize
-    words_seen = [w for w in settings.PROFANITIES_LIST if w in field_data]
-    if words_seen:
-        from django.utils.text import get_text_list
-        plural = len(words_seen)
-        raise ValidationError, ungettext("Watch your mouth! The word %s is not allowed here.",
-            "Watch your mouth! The words %s are not allowed here.", plural) % \
-            get_text_list(['"%s%s%s"' % (i[0], '-'*(len(i)-2), i[-1]) for i in words_seen], _('and'))
-
-class AlwaysMatchesOtherField(object):
-    def __init__(self, other_field_name, error_message=None):
-        self.other = other_field_name
-        self.error_message = error_message or lazy_inter(ugettext_lazy("This field must match the '%s' field."), self.other)
-        self.always_test = True
-
-    def __call__(self, field_data, all_data):
-        if field_data != all_data[self.other]:
-            raise ValidationError, self.error_message
-
-class ValidateIfOtherFieldEquals(object):
-    def __init__(self, other_field, other_value, validator_list):
-        self.other_field, self.other_value = other_field, other_value
-        self.validator_list = validator_list
-        self.always_test = True
-
-    def __call__(self, field_data, all_data):
-        if self.other_field in all_data and all_data[self.other_field] == self.other_value:
-            for v in self.validator_list:
-                v(field_data, all_data)
-
-class RequiredIfOtherFieldNotGiven(object):
-    def __init__(self, other_field_name, error_message=ugettext_lazy("Please enter something for at least one field.")):
-        self.other, self.error_message = other_field_name, error_message
-        self.always_test = True
-
-    def __call__(self, field_data, all_data):
-        if not all_data.get(self.other, False) and not field_data:
-            raise ValidationError, self.error_message
-
-class RequiredIfOtherFieldsGiven(object):
-    def __init__(self, other_field_names, error_message=ugettext_lazy("Please enter both fields or leave them both empty.")):
-        self.other, self.error_message = other_field_names, error_message
-        self.always_test = True
-
-    def __call__(self, field_data, all_data):
-        for field in self.other:
-            if all_data.get(field, False) and not field_data:
-                raise ValidationError, self.error_message
-
-class RequiredIfOtherFieldGiven(RequiredIfOtherFieldsGiven):
-    "Like RequiredIfOtherFieldsGiven, but takes a single field name instead of a list."
-    def __init__(self, other_field_name, error_message=ugettext_lazy("Please enter both fields or leave them both empty.")):
-        RequiredIfOtherFieldsGiven.__init__(self, [other_field_name], error_message)
-
-class RequiredIfOtherFieldEquals(object):
-    def __init__(self, other_field, other_value, error_message=None, other_label=None):
-        self.other_field = other_field
-        self.other_value = other_value
-        other_label = other_label or other_value
-        self.error_message = error_message or lazy_inter(ugettext_lazy("This field must be given if %(field)s is %(value)s"), {
-            'field': other_field, 'value': other_label})
-        self.always_test = True
-
-    def __call__(self, field_data, all_data):
-        if self.other_field in all_data and all_data[self.other_field] == self.other_value and not field_data:
-            raise ValidationError(self.error_message)
-
-class RequiredIfOtherFieldDoesNotEqual(object):
-    def __init__(self, other_field, other_value, other_label=None, error_message=None):
-        self.other_field = other_field
-        self.other_value = other_value
-        other_label = other_label or other_value
-        self.error_message = error_message or lazy_inter(ugettext_lazy("This field must be given if %(field)s is not %(value)s"), {
-            'field': other_field, 'value': other_label})
-        self.always_test = True
-
-    def __call__(self, field_data, all_data):
-        if self.other_field in all_data and all_data[self.other_field] != self.other_value and not field_data:
-            raise ValidationError(self.error_message)
-
-class IsLessThanOtherField(object):
-    def __init__(self, other_field_name, error_message):
-        self.other, self.error_message = other_field_name, error_message
-
-    def __call__(self, field_data, all_data):
-        if field_data > all_data[self.other]:
-            raise ValidationError, self.error_message
-
-class UniqueAmongstFieldsWithPrefix(object):
-    def __init__(self, field_name, prefix, error_message):
-        self.field_name, self.prefix = field_name, prefix
-        self.error_message = error_message or ugettext_lazy("Duplicate values are not allowed.")
-
-    def __call__(self, field_data, all_data):
-        for field_name, value in all_data.items():
-            if field_name != self.field_name and value == field_data:
-                raise ValidationError, self.error_message
-
-class NumberIsInRange(object):
-    """
-    Validator that tests if a value is in a range (inclusive).
-    """
-    def __init__(self, lower=None, upper=None, error_message=''):
-        self.lower, self.upper = lower, upper
-        if not error_message:
-            if lower and upper:
-                 self.error_message = _("This value must be between %(lower)s and %(upper)s.") % {'lower': lower, 'upper': upper}
-            elif lower:
-                self.error_message = _("This value must be at least %s.") % lower
-            elif upper:
-                self.error_message = _("This value must be no more than %s.") % upper
-        else:
-            self.error_message = error_message
-
-    def __call__(self, field_data, all_data):
-        # Try to make the value numeric. If this fails, we assume another
-        # validator will catch the problem.
-        try:
-            val = float(field_data)
-        except ValueError:
-            return
-
-        # Now validate
-        if self.lower and self.upper and (val < self.lower or val > self.upper):
-            raise ValidationError(self.error_message)
-        elif self.lower and val < self.lower:
-            raise ValidationError(self.error_message)
-        elif self.upper and val > self.upper:
-            raise ValidationError(self.error_message)
-
-class IsAPowerOf(object):
-    """
-    Usage: If you create an instance of the IsPowerOf validator:
-        v = IsAPowerOf(2)
-
-    The following calls will succeed:
-        v(4, None)
-        v(8, None)
-        v(16, None)
-
-    But this call:
-        v(17, None)
-    will raise "django.core.validators.ValidationError: ['This value must be a power of 2.']"
-    """
-    def __init__(self, power_of):
-        self.power_of = power_of
-
-    def __call__(self, field_data, all_data):
-        from math import log
-        val = log(int(field_data)) / log(self.power_of)
-        if val != int(val):
-            raise ValidationError, _("This value must be a power of %s.") % self.power_of
-
-class IsValidDecimal(object):
-    def __init__(self, max_digits, decimal_places):
-        self.max_digits, self.decimal_places = max_digits, decimal_places
-
-    def __call__(self, field_data, all_data):
-        try:
-            val = Decimal(field_data)
-        except DecimalException:
-            raise ValidationError, _("Please enter a valid decimal number.")
-
-        pieces = str(val).lstrip("-").split('.')
-        decimals = (len(pieces) == 2) and len(pieces[1]) or 0
-        digits = len(pieces[0])
-
-        if digits + decimals > self.max_digits:
-            raise ValidationError, ungettext("Please enter a valid decimal number with at most %s total digit.",
-                "Please enter a valid decimal number with at most %s total digits.", self.max_digits) % self.max_digits
-        if digits > (self.max_digits - self.decimal_places):
-            raise ValidationError, ungettext( "Please enter a valid decimal number with a whole part of at most %s digit.",
-                "Please enter a valid decimal number with a whole part of at most %s digits.", str(self.max_digits-self.decimal_places)) % str(self.max_digits-self.decimal_places)
-        if decimals > self.decimal_places:
-            raise ValidationError, ungettext("Please enter a valid decimal number with at most %s decimal place.",
-                "Please enter a valid decimal number with at most %s decimal places.", self.decimal_places) % self.decimal_places
-
-def isValidFloat(field_data, all_data):
-    data = smart_str(field_data)
-    try:
-        float(data)
-    except ValueError:
-        raise ValidationError, _("Please enter a valid floating point number.")
-
-class HasAllowableSize(object):
-    """
-    Checks that the file-upload field data is a certain size. min_size and
-    max_size are measurements in bytes.
-    """
-    def __init__(self, min_size=None, max_size=None, min_error_message=None, max_error_message=None):
-        self.min_size, self.max_size = min_size, max_size
-        self.min_error_message = min_error_message or lazy_inter(ugettext_lazy("Make sure your uploaded file is at least %s bytes big."), min_size)
-        self.max_error_message = max_error_message or lazy_inter(ugettext_lazy("Make sure your uploaded file is at most %s bytes big."), max_size)
-
-    def __call__(self, field_data, all_data):
-        try:
-            content = field_data.read()
-        except TypeError:
-            raise ValidationError, ugettext_lazy("No file was submitted. Check the encoding type on the form.")
-        if self.min_size is not None and len(content) < self.min_size:
-            raise ValidationError, self.min_error_message
-        if self.max_size is not None and len(content) > self.max_size:
-            raise ValidationError, self.max_error_message
-
-class MatchesRegularExpression(object):
-    """
-    Checks that the field matches the given regular-expression. The regex
-    should be in string format, not already compiled.
-    """
-    def __init__(self, regexp, error_message=ugettext_lazy("The format for this field is wrong.")):
-        self.regexp = re.compile(regexp)
-        self.error_message = error_message
-
-    def __call__(self, field_data, all_data):
-        if not self.regexp.search(field_data):
-            raise ValidationError(self.error_message)
-
-class AnyValidator(object):
-    """
-    This validator tries all given validators. If any one of them succeeds,
-    validation passes. If none of them succeeds, the given message is thrown
-    as a validation error. The message is rather unspecific, so it's best to
-    specify one on instantiation.
-    """
-    def __init__(self, validator_list=None, error_message=ugettext_lazy("This field is invalid.")):
-        if validator_list is None: validator_list = []
-        self.validator_list = validator_list
-        self.error_message = error_message
-        for v in validator_list:
-            if hasattr(v, 'always_test'):
-                self.always_test = True
-
-    def __call__(self, field_data, all_data):
-        for v in self.validator_list:
-            try:
-                v(field_data, all_data)
-                return
-            except ValidationError, e:
-                pass
-        raise ValidationError(self.error_message)
-
-class URLMimeTypeCheck(object):
-    "Checks that the provided URL points to a document with a listed mime type"
-    class CouldNotRetrieve(ValidationError):
-        pass
-    class InvalidContentType(ValidationError):
-        pass
-
-    def __init__(self, mime_type_list):
-        self.mime_type_list = mime_type_list
-
-    def __call__(self, field_data, all_data):
-        import urllib2
-        try:
-            isValidURL(field_data, all_data)
-        except ValidationError:
-            raise
-        try:
-            info = urllib2.urlopen(field_data).info()
-        except (urllib2.HTTPError, urllib2.URLError):
-            raise URLMimeTypeCheck.CouldNotRetrieve, _("Could not retrieve anything from %s.") % field_data
-        content_type = info['content-type']
-        if content_type not in self.mime_type_list:
-            raise URLMimeTypeCheck.InvalidContentType, _("The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'.") % {
-                'url': field_data, 'contenttype': content_type}
-
-class RelaxNGCompact(object):
-    "Validate against a Relax NG compact schema"
-    def __init__(self, schema_path, additional_root_element=None):
-        self.schema_path = schema_path
-        self.additional_root_element = additional_root_element
-
-    def __call__(self, field_data, all_data):
-        import os, tempfile
-        if self.additional_root_element:
-            field_data = '<%(are)s>%(data)s\n</%(are)s>' % {
-                'are': self.additional_root_element,
-                'data': field_data
-            }
-        filename = tempfile.mktemp() # Insecure, but nothing else worked
-        fp = open(filename, 'w')
-        fp.write(field_data)
-        fp.close()
-        if not os.path.exists(settings.JING_PATH):
-            raise Exception, "%s not found!" % settings.JING_PATH
-        p = os.popen('%s -c %s %s' % (settings.JING_PATH, self.schema_path, filename))
-        errors = [line.strip() for line in p.readlines()]
-        p.close()
-        os.unlink(filename)
-        display_errors = []
-        lines = field_data.split('\n')
-        for error in errors:
-            ignored, line, level, message = error.split(':', 3)
-            # Scrape the Jing error messages to reword them more nicely.
-            m = re.search(r'Expected "(.*?)" to terminate element starting on line (\d+)', message)
-            if m:
-                display_errors.append(_('Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "%(start)s".)') % \
-                    {'tag':m.group(1).replace('/', ''), 'line':m.group(2), 'start':lines[int(m.group(2)) - 1][:30]})
-                continue
-            if message.strip() == 'text not allowed here':
-                display_errors.append(_('Some text starting on line %(line)s is not allowed in that context. (Line starts with "%(start)s".)') % \
-                    {'line':line, 'start':lines[int(line) - 1][:30]})
-                continue
-            m = re.search(r'\s*attribute "(.*?)" not allowed at this point; ignored', message)
-            if m:
-                display_errors.append(_('"%(attr)s" on line %(line)s is an invalid attribute. (Line starts with "%(start)s".)') % \
-                    {'attr':m.group(1), 'line':line, 'start':lines[int(line) - 1][:30]})
-                continue
-            m = re.search(r'\s*unknown element "(.*?)"', message)
-            if m:
-                display_errors.append(_('"<%(tag)s>" on line %(line)s is an invalid tag. (Line starts with "%(start)s".)') % \
-                    {'tag':m.group(1), 'line':line, 'start':lines[int(line) - 1][:30]})
-                continue
-            if message.strip() == 'required attributes missing':
-                display_errors.append(_('A tag on line %(line)s is missing one or more required attributes. (Line starts with "%(start)s".)') % \
-                    {'line':line, 'start':lines[int(line) - 1][:30]})
-                continue
-            m = re.search(r'\s*bad value for attribute "(.*?)"', message)
-            if m:
-                display_errors.append(_('The "%(attr)s" attribute on line %(line)s has an invalid value. (Line starts with "%(start)s".)') % \
-                    {'attr':m.group(1), 'line':line, 'start':lines[int(line) - 1][:30]})
-                continue
-            # Failing all those checks, use the default error message.
-            display_error = 'Line %s: %s [%s]' % (line, message, level.strip())
-            display_errors.append(display_error)
-        if len(display_errors) > 0:
-            raise ValidationError, display_errors

django/db/models/__init__.py

 from django.conf import settings
 from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
-from django.core import validators
 from django.db import connection
 from django.db.models.loading import get_apps, get_app, get_models, get_model, register_models
 from django.db.models.query import Q
 from django.db.models.fields import *
 from django.db.models.fields.subclassing import SubfieldBase
 from django.db.models.fields.files import FileField, ImageField
-from django.db.models.fields.related import ForeignKey, OneToOneField, ManyToManyField, ManyToOneRel, ManyToManyRel, OneToOneRel, TABULAR, STACKED
+from django.db.models.fields.related import ForeignKey, OneToOneField, ManyToManyField, ManyToOneRel, ManyToManyRel, OneToOneRel
 from django.db.models import signals
 
 # Admin stages.

django/db/models/base.py

 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.
-from django.core import validators
+import django.db.models.manager     # Imported to register signal handler.
 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError
 from django.db.models.fields import AutoField
 from django.db.models.fields.related import OneToOneRel, ManyToOneRel, OneToOneField
 
         # 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:

django/db/models/fields/__init__.py

 import copy
 import datetime
 import os
+import re
 import time
 try:
     import decimal
 from django.db.models.query_utils import QueryWrapper
 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.core import exceptions
 from django.utils.datastructures import DictWrapper
 from django.utils.functional import curry
 from django.utils.itercompat import tee
 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.
 
     def __init__(self, verbose_name=None, name=None, primary_key=False,
             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,
-            auto_created=False):
+            db_index=False, rel=None, default=NOT_PROVIDED, editable=True,
+            serialize=True, unique_for_date=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
         self.primary_key = primary_key
         # option whenever '' is a possible value.
         if self.empty_strings_allowed and connection.features.interprets_empty_strings_as_nulls:
             self.null = True
-        self.core, self.rel, self.default = core, rel, default
+        self.rel = rel
+        self.default = 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 []
     def to_python(self, value):
         """
         Converts the input value into the expected Python data type, raising
-        validators.ValidationError if the data can't be converted. Returns the
-        converted value. Subclasses should override this.
+        django.core.exceptions.ValidationError if the data can't be converted.
+        Returns the converted value. Subclasses should override this.
         """
         return value
 
             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."""
         else:
             return self.get_default()
 
-    def flatten_data(self, follow, obj=None):
+    def value_to_string(self, obj):
         """
-        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.
+        Returns a string value of this field from the passed obj.
+        This is used by the serialization framework.
         """
-        return {self.attname: self._get_val_from_obj(obj)}
-
-    def get_follow(self, override=None):
-        if override != None:
-            return override
-        else:
-            return self.editable
+        return smart_unicode(self._get_val_from_obj(obj))
 
     def bind(self, fieldmapping, original, bound_field_class):
         return bound_field_class(self, fieldmapping, original)
         try:
             return int(value)
         except (TypeError, ValueError):
-            raise validators.ValidationError, _("This value must be an integer.")
+            raise exceptions.ValidationError(
+                _("This value must be an integer."))
 
     def get_db_prep_value(self, value):
         if value is None:
             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)
         if value in (True, False): return value
         if value in ('t', 'True', '1'): return True
         if value in ('f', 'False', '0'): return False
-        raise validators.ValidationError, _("This value must be either True or False.")
+        raise exceptions.ValidationError(
+            _("This value must be either True or False."))
 
     def get_db_prep_value(self, value):
         if value is None:
             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"
 
             if self.null:
                 return value
             else:
-                raise validators.ValidationError, ugettext_lazy("This field cannot be null.")
+                raise exceptions.ValidationError(
+                    ugettext_lazy("This field cannot be null."))
         return smart_unicode(value)
 
     def formfield(self, **kwargs):
 
 # TODO: Maybe move this into contrib, because it's specialized.
 class CommaSeparatedIntegerField(CharField):
-    def get_manipulator_field_objs(self):
-        return [oldforms.CommaSeparatedIntegerField]
+    pass
+
+ansi_date_re = re.compile(r'^\d{4}-\d{1,2}-\d{1,2}$')
 
 class DateField(Field):
     empty_strings_allowed = False
             return value.date()
         if isinstance(value, datetime.date):
             return value
-        validators.isValidANSIDate(value, None)
+
+        if not ansi_date_re.search(value):
+            raise exceptions.ValidationError(
+                _('Enter a valid date in YYYY-MM-DD format.'))
+        # Now that we have the date string in YYYY-MM-DD format, check to make
+        # sure it's a valid date.
+        # We could use time.strptime here and catch errors, but datetime.date
+        # produces much friendlier error messages.
+        year, month, day = map(int, value.split('-'))
         try:
-            return datetime.date(*time.strptime(value, '%Y-%m-%d')[:3])
-        except ValueError:
-            raise validators.ValidationError, _('Enter a valid date in YYYY-MM-DD format.')
+            return datetime.date(year, month, day)
+        except ValueError, e:
+            msg = _('Invalid date: %s') % _(str(e))
+            raise exceptions.ValidationError(msg)
 
     def pre_save(self, model_instance, add):
         if self.auto_now or (self.auto_now_add and add):
             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.
         # 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 value_to_string(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}
                 value, usecs = value.split('.')
                 usecs = int(usecs)
             except ValueError:
-                raise validators.ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.')
+                raise exceptions.ValidationError(
+                    _('Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.'))
         else:
             usecs = 0
         kwargs = {'microsecond': usecs}
                     return datetime.datetime(*time.strptime(value, '%Y-%m-%d')[:3],
                                              **kwargs)
                 except ValueError:
-                    raise validators.ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.')
+                    raise exceptions.ValidationError(
+                        _('Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.'))
 
     def get_db_prep_value(self, value):
         # 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 value_to_string(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}
         try:
             return decimal.Decimal(value)
         except decimal.InvalidOperation:
-            raise validators.ValidationError(
+            raise exceptions.ValidationError(
                 _("This value must be a decimal number."))
 
     def _format(self, value):
         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,
         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)
         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"
 
             return None
         return float(value)
 
-    def get_manipulator_field_objs(self):
-        return [oldforms.FloatField]
-
     def get_internal_type(self):
         return "FloatField"
 
             return None
         return int(value)
 
-    def get_manipulator_field_objs(self):
-        return [oldforms.IntegerField]
-
     def get_internal_type(self):
         return "IntegerField"
 
         try:
             return int(value)
         except (TypeError, ValueError):
-            raise validators.ValidationError, _("This value must be an integer.")
-                
+            raise exceptions.ValidationError(
+                _("This value must be an integer."))
+
     def formfield(self, **kwargs):
         defaults = {'form_class': forms.IntegerField}
         defaults.update(kwargs)
         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"
 
         if value in ('None'): return None
         if value in ('t', 'True', '1'): return True
         if value in ('f', 'False', '0'): return False
-        raise validators.ValidationError, _("This value must be either None, True or False.")
+        raise exceptions.ValidationError(
+            _("This value must be either None, True or False."))
 
     def get_db_prep_value(self, value):
         if value is None:
             return None
         return bool(value)
 
-    def get_manipulator_field_objs(self):
-        return [oldforms.NullBooleanField]
-
     def formfield(self, **kwargs):
         defaults = {
             'form_class': forms.NullBooleanField,
         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"
 
         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"
 
         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"
 
 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
         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"
 
                 value, usecs = value.split('.')
                 usecs = int(usecs)
             except ValueError:
-                raise validators.ValidationError, _('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.')
+                raise exceptions.ValidationError(
+                    _('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.'))
         else:
             usecs = 0
         kwargs = {'microsecond': usecs}
                 return datetime.time(*time.strptime(value, '%H:%M')[3:5],
                                          **kwargs)
             except ValueError:
-                raise validators.ValidationError, _('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.')
+                raise exceptions.ValidationError(
+                    _('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.'))
 
     def pre_save(self, model_instance, add):
         if self.auto_now or (self.auto_now_add and add):
         # 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 value_to_string(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}
 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"
 
     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)]
-

django/db/models/fields/files.py

 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
 
 class FieldFile(File):
     attr_class = FieldFile
 
     def __init__(self, verbose_name=None, name=None, upload_to='', storage=None, **kwargs):
-        for arg in ('core', 'primary_key', 'unique'):
+        for arg in ('primary_key', 'unique'):
             if arg in kwargs:
                 raise TypeError("'%s' is not a valid argument for %s." % (arg, self.__class__))
 
             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))
             # 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]
         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)

django/db/models/fields/related.py

 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.core import exceptions
 from django import forms
 
 try:
 except NameError:
     from sets import Set as set   # Python 2.3 fallback
 
-# Values for Relation.edit_inline.
-TABULAR, STACKED = 1, 2
-
 RECURSIVE_RELATIONSHIP_CONSTANT = 'self'
 
 pending_lookups = {}
 
 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):
         manager.add(*value)
 
 class ManyToOneRel(object):
-    def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None,
-            max_num_in_admin=None, num_extra_on_change=1, edit_inline=False,
-            related_name=None, limit_choices_to=None, lookup_overrides=None,
-            parent_link=False):
+    def __init__(self, to, field_name, related_name=None,
+            limit_choices_to=None, lookup_overrides=None, parent_link=False):
         try:
             to._meta
         except AttributeError: # to._meta doesn't exist, so it must be RECURSIVE_RELATIONSHIP_CONSTANT
             assert isinstance(to, basestring), "'to' must be either a model, a model name or the string %r" % RECURSIVE_RELATIONSHIP_CONSTANT
         self.to, self.field_name = to, field_name
-        self.num_in_admin, self.edit_inline = num_in_admin, edit_inline
-        self.min_num_in_admin, self.max_num_in_admin = min_num_in_admin, max_num_in_admin
-        self.num_extra_on_change, self.related_name = num_extra_on_change, related_name
+        self.related_name = related_name
         if limit_choices_to is None:
             limit_choices_to = {}
         self.limit_choices_to = limit_choices_to
         return data[0]
 
 class OneToOneRel(ManyToOneRel):
-    def __init__(self, to, field_name, num_in_admin=0, min_num_in_admin=None,
-            max_num_in_admin=None, num_extra_on_change=None, edit_inline=False,
-            related_name=None, limit_choices_to=None, lookup_overrides=None,
-            parent_link=False):
-        # NOTE: *_num_in_admin and num_extra_on_change are intentionally
-        # ignored here. We accept them as parameters only to match the calling
-        # signature of ManyToOneRel.__init__().
-        super(OneToOneRel, self).__init__(to, field_name, num_in_admin,
-                edit_inline=edit_inline, related_name=related_name,
-                limit_choices_to=limit_choices_to,
+    def __init__(self, to, field_name, related_name=None,
+            limit_choices_to=None, lookup_overrides=None, parent_link=False):
+        super(OneToOneRel, self).__init__(to, field_name,
+                related_name=related_name, limit_choices_to=limit_choices_to,
                 lookup_overrides=lookup_overrides, parent_link=parent_link)
         self.multiple = False
 
 class ManyToManyRel(object):
-    def __init__(self, to, num_in_admin=0, related_name=None,
-        limit_choices_to=None, symmetrical=True, through=None):
+    def __init__(self, to, related_name=None, limit_choices_to=None,
+            symmetrical=True, through=None):
         self.to = to
-        self.num_in_admin = num_in_admin
         self.related_name = related_name
         if limit_choices_to is None:
             limit_choices_to = {}
         self.limit_choices_to = limit_choices_to
-        self.edit_inline = False
         self.symmetrical = symmetrical
         self.multiple = True
         self.through = through
         kwargs['verbose_name'] = kwargs.get('verbose_name', None)
 
         kwargs['rel'] = rel_class(to, to_field,
-            num_in_admin=kwargs.pop('num_in_admin', 3),
-            min_num_in_admin=kwargs.pop('min_num_in_admin', None),
-            max_num_in_admin=kwargs.pop('max_num_in_admin', None),
-            num_extra_on_change=kwargs.pop('num_extra_on_change', 1),
-            edit_inline=kwargs.pop('edit_inline', False),
             related_name=kwargs.pop('related_name', None),
             limit_choices_to=kwargs.pop('limit_choices_to', None),
             lookup_overrides=kwargs.pop('lookup_overrides', None),
     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()
             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 value_to_string(self, obj):
         if not obj:
             # In required many-to-one fields with only one available choice,
             # select that one available choice. Note: For SelectFields
             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.value_to_string(self, obj)
 
     def contribute_to_class(self, cls, name):
         super(ForeignKey, self).contribute_to_class(cls, name)
     """
     def __init__(self, to, to_field=None, **kwargs):
         kwargs['unique'] = True
-        if 'num_in_admin' not in kwargs:
-            kwargs['num_in_admin'] = 0
         super(OneToOneField, self).__init__(to, to_field, OneToOneRel, **kwargs)
 
     def contribute_to_related_class(self, cls, related):
 
         kwargs['verbose_name'] = kwargs.get('verbose_name', None)
         kwargs['rel'] = ManyToManyRel(to,
-            num_in_admin=kwargs.pop('num_in_admin', 0),
             related_name=kwargs.pop('related_name', None),
             limit_choices_to=kwargs.pop('limit_choices_to', None),
             symmetrical=kwargs.pop('symmetrical', True),
         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)
 
         objects = mod._default_manager.in_bulk(pks)
         if len(objects) != len(pks):
             badkeys = [k for k in pks if k not in objects]
-            raise validators.ValidationError, ungettext("Please enter valid %(self)s IDs. The value %(value)r is invalid.",
-                    "Please enter valid %(self)s IDs. The values %(value)r are invalid.", len(badkeys)) % {
+            raise exceptions.ValidationError(
+                ungettext("Please enter valid %(self)s IDs. The value %(value)r is invalid.",
+                          "Please enter valid %(self)s IDs. The values %(value)r are invalid.",
+                          len(badkeys)) % {
                 'self': self.verbose_name,
                 'value': len(badkeys) == 1 and badkeys[0] or tuple(badkeys),
-            }
+            })
 
-    def flatten_data(self, follow, obj = None):
-        new_data = {}
+    def value_to_string(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:
+            if not self.blank:
                 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)

django/db/models/manipulators.py

-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))