app/django/db/models/fields/__init__.py
changeset 323 ff1a9aa48cfd
parent 54 03e267d67478
--- a/app/django/db/models/fields/__init__.py	Tue Oct 14 12:36:55 2008 +0000
+++ b/app/django/db/models/fields/__init__.py	Tue Oct 14 16:00:59 2008 +0000
@@ -1,58 +1,38 @@
 import copy
 import datetime
 import os
+import re
 import time
 try:
     import decimal
 except ImportError:
     from django.utils import _decimal as decimal    # for Python 2.3
 
-from django.db import get_creation_module
+from django.db import connection
 from django.db.models import signals
 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 newforms as forms
-from django.core.exceptions import ObjectDoesNotExist
+from django import forms
+from django.core import exceptions
+from django.utils.datastructures import DictWrapper
 from django.utils.functional import curry
 from django.utils.itercompat import tee
 from django.utils.text import capfirst
 from django.utils.translation import ugettext_lazy, ugettext as _
 from django.utils.encoding import smart_unicode, force_unicode, smart_str
-from django.utils.maxlength import LegacyMaxlength
+from django.utils import datetime_safe
 
 class NOT_PROVIDED:
     pass
 
-# Values for filter_interface.
-HORIZONTAL, VERTICAL = 1, 2
-
 # The values to use for "blank" in SelectFields. Will be appended to the start of most "choices" lists.
 BLANK_CHOICE_DASH = [("", "---------")]
 BLANK_CHOICE_NONE = [("", "None")]
 
-# prepares a value for use in a LIKE query
-prep_for_like_query = lambda x: smart_unicode(x).replace("\\", "\\\\").replace("%", "\%").replace("_", "\_")
-
-# returns the <ul> class for a given radio_admin value
-get_ul_class = lambda x: 'radiolist%s' % ((x == HORIZONTAL) and ' inline' or '')
-
 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.
@@ -69,10 +49,6 @@
 #     getattr(obj, opts.pk.attname)
 
 class Field(object):
-    # Provide backwards compatibility for the maxlength attribute and
-    # argument for this class and all subclasses.
-    __metaclass__ = LegacyMaxlength
-
     # Designates whether empty strings fundamentally are allowed at the
     # database level.
     empty_strings_allowed = True
@@ -85,32 +61,30 @@
 
     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, prepopulate_from=None,
-            unique_for_date=None, unique_for_month=None, unique_for_year=None,
-            validator_list=None, choices=None, radio_admin=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
-        self.max_length, self.unique = max_length, unique
+        self.max_length, self._unique = max_length, unique
         self.blank, self.null = blank, null
         # Oracle treats the empty string ('') as null, so coerce the null
         # option whenever '' is a possible value.
-        if self.empty_strings_allowed and settings.DATABASE_ENGINE == 'oracle':
+        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.prepopulate_from = prepopulate_from
         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 []
-        self.radio_admin = radio_admin
         self.help_text = help_text
         self.db_column = db_column
         self.db_tablespace = db_tablespace or settings.DEFAULT_INDEX_TABLESPACE
+        self.auto_created = auto_created
 
         # Set db_index to True if the field has a relationship and doesn't explicitly set db_index.
         self.db_index = db_index
@@ -139,8 +113,8 @@
     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
 
@@ -159,43 +133,26 @@
         # as the TextField Django field type, which means XMLField's
         # get_internal_type() returns 'TextField'.
         #
-        # But the limitation of the get_internal_type() / DATA_TYPES approach
+        # But the limitation of the get_internal_type() / data_types approach
         # is that it cannot handle database column types that aren't already
         # mapped to one of the built-in Django field types. In this case, you
         # can implement db_type() instead of get_internal_type() to specify
         # exactly which wacky database column type you want to use.
+        data = DictWrapper(self.__dict__, connection.ops.quote_name, "qn_")
         try:
-            return get_creation_module().DATA_TYPES[self.get_internal_type()] % self.__dict__
+            return connection.creation.data_types[self.get_internal_type()] % data
         except KeyError:
             return None
 
-    def validate_full(self, field_data, all_data):
-        """
-        Returns a list of errors for this field. This is the main interface,
-        as it encapsulates some basic validation logic used by all fields.
-        Subclasses should implement validate(), not validate_full().
-        """
-        if not self.blank and not field_data:
-            return [_('This field is required.')]
-        try:
-            self.validate(field_data, all_data)
-        except validators.ValidationError, e:
-            return e.messages
-        return []
-
-    def validate(self, field_data, all_data):
-        """
-        Raises validators.ValidationError if field_data has any errors.
-        Subclasses should override this to specify field-specific validation
-        logic. This method should assume field_data has already been converted
-        into the appropriate data type by Field.to_python().
-        """
-        pass
+    def unique(self):
+        return self._unique or self.primary_key
+    unique = property(unique)
 
     def set_attributes_from_name(self, name):
         self.name = name
         self.attname, self.column = self.get_attname_column()
-        self.verbose_name = self.verbose_name or (name and name.replace('_', ' '))
+        if self.verbose_name is None and name:
+            self.verbose_name = name.replace('_', ' ')
 
     def contribute_to_class(self, cls, name):
         self.set_attributes_from_name(name)
@@ -221,27 +178,38 @@
         "Returns field's value just before saving."
         return getattr(model_instance, self.attname)
 
+    def get_db_prep_value(self, value):
+        """Returns field's value prepared for interacting with the database
+        backend.
+
+        Used by the default implementations of ``get_db_prep_save``and
+        `get_db_prep_lookup```
+        """
+        return value
+
     def get_db_prep_save(self, value):
         "Returns field's value prepared for saving into a database."
-        return value
+        return self.get_db_prep_value(value)
 
     def get_db_prep_lookup(self, lookup_type, value):
         "Returns field's value prepared for database lookup."
         if hasattr(value, 'as_sql'):
             sql, params = value.as_sql()
             return QueryWrapper(('(%s)' % sql), params)
-        if lookup_type in ('exact', 'regex', 'iregex', 'gt', 'gte', 'lt', 'lte', 'month', 'day', 'search'):
+        if lookup_type in ('regex', 'iregex', 'month', 'day', 'search'):
             return [value]
+        elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte'):
+            return [self.get_db_prep_value(value)]
         elif lookup_type in ('range', 'in'):
-            return value
+            return [self.get_db_prep_value(v) for v in value]
         elif lookup_type in ('contains', 'icontains'):
-            return ["%%%s%%" % prep_for_like_query(value)]
+            return ["%%%s%%" % connection.ops.prep_for_like_query(value)]
         elif lookup_type == 'iexact':
-            return [prep_for_like_query(value)]
+            return [connection.ops.prep_for_iexact_query(value)]
         elif lookup_type in ('startswith', 'istartswith'):
-            return ["%s%%" % prep_for_like_query(value)]
+            return ["%s%%" % connection.ops.prep_for_like_query(value)]
         elif lookup_type in ('endswith', 'iendswith'):
-            return ["%%%s" % prep_for_like_query(value)]
+            return ["%%%s" % connection.ops.prep_for_like_query(value)]
         elif lookup_type == 'isnull':
             return []
         elif lookup_type == 'year':
@@ -249,16 +217,12 @@
                 value = int(value)
             except ValueError:
                 raise ValueError("The __year lookup type requires an integer argument")
-            if settings.DATABASE_ENGINE == 'sqlite3':
-                first = '%s-01-01'
-                second = '%s-12-31 23:59:59.999999'
-            elif settings.DATABASE_ENGINE == 'oracle' and self.get_internal_type() == 'DateField':
-                first = '%s-01-01'
-                second = '%s-12-31'
+
+            if self.get_internal_type() == 'DateField':
+                return connection.ops.year_lookup_bounds_for_date_field(value)
             else:
-                first = '%s-01-01 00:00:00'
-                second = '%s-12-31 23:59:59.999999'
-            return [first % value, second % value]
+                return connection.ops.year_lookup_bounds(value)
+
         raise TypeError("Field has invalid lookup: %s" % lookup_type)
 
     def has_default(self):
@@ -267,107 +231,20 @@
 
     def get_default(self):
         "Returns the default value for this field."
-        if self.default is not NOT_PROVIDED:
+        if self.has_default():
             if callable(self.default):
                 return self.default()
             return force_unicode(self.default, strings_only=True)
-        if not self.empty_strings_allowed or (self.null and settings.DATABASE_ENGINE != 'oracle'):
+        if not self.empty_strings_allowed or (self.null and not connection.features.interprets_empty_strings_as_nulls):
             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:
-            if self.radio_admin:
-                field_objs = [oldforms.RadioSelectField]
-                params['ul_class'] = get_ul_class(self.radio_admin)
-            else:
-                field_objs = [oldforms.SelectField]
-
-            params['choices'] = self.get_choices_default()
-        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 or (self.primary_key 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 a list of tuples used as SelectField choices for this field."
+        """Returns choices with a default blank choices included, for use
+        as SelectField choices for this field."""
         first_choice = include_blank and blank_choice or []
         if self.choices:
             return first_choice + list(self.choices)
@@ -379,10 +256,12 @@
         return first_choice + lst
 
     def get_choices_default(self):
-        if self.radio_admin:
-            return self.get_choices(include_blank=self.blank, blank_choice=BLANK_CHOICE_NONE)
-        else:
-            return self.get_choices()
+        return self.get_choices()
+
+    def get_flatchoices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH):
+        "Returns flattened choices with a default blank choice included."
+        first_choice = include_blank and blank_choice or []
+        return first_choice + list(self.flatchoices)
 
     def _get_val_from_obj(self, obj):
         if obj:
@@ -390,19 +269,12 @@
         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.
+    def value_to_string(self, obj):
         """
-        return {self.attname: self._get_val_from_obj(obj)}
-
-    def get_follow(self, override=None):
-        if override != None:
-            return override
-        else:
-            return self.editable
+        Returns a string value of this field from the passed obj.
+        This is used by the serialization framework.
+        """
+        return smart_unicode(self._get_val_from_obj(obj))
 
     def bind(self, fieldmapping, original, bound_field_class):
         return bound_field_class(self, fieldmapping, original)
@@ -415,16 +287,43 @@
             return self._choices
     choices = property(_get_choices)
 
+    def _get_flatchoices(self):
+        """Flattened version of choices tuple."""
+        flat = []
+        for choice, value in self.choices:
+            if type(value) in (list, tuple):
+                flat.extend(value)
+            else:
+                flat.append((choice,value))
+        return flat
+    flatchoices = property(_get_flatchoices)
+
     def save_form_data(self, instance, data):
         setattr(instance, self.name, data)
 
     def formfield(self, form_class=forms.CharField, **kwargs):
-        "Returns a django.newforms.Field instance for this database Field."
+        "Returns a django.forms.Field instance for this database Field."
         defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
-        if self.choices:
-            defaults['widget'] = forms.Select(choices=self.get_choices(include_blank=self.blank or not (self.has_default() or 'initial' in kwargs)))
         if self.has_default():
             defaults['initial'] = self.get_default()
+            if callable(self.default):
+                defaults['show_hidden_initial'] = True
+        if self.choices:
+            # Fields with choices get special treatment. 
+            include_blank = self.blank or not (self.has_default() or 'initial' in kwargs)
+            defaults['choices'] = self.get_choices(include_blank=include_blank)
+            defaults['coerce'] = self.to_python
+            if self.null:
+                defaults['empty_value'] = None
+            form_class = forms.TypedChoiceField
+            # Many of the subclass-specific formfield arguments (min_value,
+            # max_value) don't apply for choice fields, so be sure to only pass
+            # the values that TypedChoiceField will understand.
+            for k in kwargs.keys():
+                if k not in ('coerce', 'empty_value', 'choices', 'required',
+                             'widget', 'label', 'initial', 'help_text',
+                             'error_messages'):
+                    del kwargs[k]
         defaults.update(kwargs)
         return form_class(**defaults)
 
@@ -445,23 +344,13 @@
         try:
             return int(value)
         except (TypeError, ValueError):
-            raise validators.ValidationError, _("This value must be an integer.")
-
-    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)
+            raise exceptions.ValidationError(
+                _("This value must be an integer."))
 
-    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:
+    def get_db_prep_value(self, value):
+        if value is None:
             return None
-        return Field.get_manipulator_new_data(self, new_data, rel)
+        return int(value)
 
     def contribute_to_class(self, cls, name):
         assert not cls._meta.has_auto_field, "A model can't have more than one AutoField."
@@ -475,6 +364,8 @@
 class BooleanField(Field):
     def __init__(self, *args, **kwargs):
         kwargs['blank'] = True
+        if 'default' not in kwargs and not kwargs.get('null'):
+            kwargs['default'] = False
         Field.__init__(self, *args, **kwargs)
 
     def get_internal_type(self):
@@ -484,10 +375,22 @@
         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_manipulator_field_objs(self):
-        return [oldforms.CheckboxField]
+    def get_db_prep_lookup(self, lookup_type, value):
+        # Special-case handling for filters coming from a web request (e.g. the
+        # admin interface). Only works for scalar values (not lists). If you're
+        # passing in a list, you might as well make things the right type when
+        # constructing the list.
+        if value in ('1', '0'):
+            value = bool(int(value))
+        return super(BooleanField, self).get_db_prep_lookup(lookup_type, value)
+
+    def get_db_prep_value(self, value):
+        if value is None:
+            return None
+        return bool(value)
 
     def formfield(self, **kwargs):
         defaults = {'form_class': forms.BooleanField}
@@ -495,9 +398,6 @@
         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"
 
@@ -508,7 +408,8 @@
             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):
@@ -518,8 +419,19 @@
 
 # TODO: Maybe move this into contrib, because it's specialized.
 class CommaSeparatedIntegerField(CharField):
-    def get_manipulator_field_objs(self):
-        return [oldforms.CommaSeparatedIntegerField]
+    def formfield(self, **kwargs):
+        defaults = {
+            'form_class': forms.RegexField,
+            'regex': '^[\d,]+$',
+            'max_length': self.max_length,
+            'error_messages': {
+                'invalid': _(u'Enter only digits separated by commas.'),
+            }
+        }
+        defaults.update(kwargs)
+        return super(CommaSeparatedIntegerField, self).formfield(**defaults)
+
+ansi_date_re = re.compile(r'^\d{4}-\d{1,2}-\d{1,2}$')
 
 class DateField(Field):
     empty_strings_allowed = False
@@ -541,20 +453,20 @@
             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.')
-
-    def get_db_prep_lookup(self, lookup_type, value):
-        if lookup_type == 'range':
-            value = [smart_unicode(v) for v in value]
-        elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte') and hasattr(value, 'strftime'):
-            value = value.strftime('%Y-%m-%d')
-        else:
-            value = smart_unicode(value)
-        return Field.get_db_prep_lookup(self, lookup_type, value)
+            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):
@@ -572,30 +484,24 @@
             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.
+        if lookup_type in ('month', 'day'):
+            return [force_unicode(value)]
+        return super(DateField, self).get_db_prep_lookup(lookup_type, value)
 
-    def get_db_prep_save(self, value):
-        # Casts dates into string format for entry into database.
-        if value is not None:
-            try:
-                value = value.strftime('%Y-%m-%d')
-            except AttributeError:
-                # If value is already a string it won't have a strftime method,
-                # so we'll just let it pass through.
-                pass
-        return Field.get_db_prep_save(self, value)
+    def get_db_prep_value(self, value):
+        # 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)
-        return {self.attname: (val is not None and val.strftime("%Y-%m-%d") or '')}
+        if val is None:
+            data = ''
+        else:
+            data = datetime_safe.new_date(val).strftime("%Y-%m-%d")
+        return data
 
     def formfield(self, **kwargs):
         defaults = {'form_class': forms.DateField}
@@ -613,57 +519,48 @@
             return value
         if isinstance(value, datetime.date):
             return datetime.datetime(value.year, value.month, value.day)
+
+        # Attempt to parse a datetime:
+        value = smart_str(value)
+        # split usecs, because they are not recognized by strptime.
+        if '.' in value:
+            try:
+                value, usecs = value.split('.')
+                usecs = int(usecs)
+            except ValueError:
+                raise exceptions.ValidationError(
+                    _('Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.'))
+        else:
+            usecs = 0
+        kwargs = {'microsecond': usecs}
         try: # Seconds are optional, so try converting seconds first.
-            return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M:%S')[:6])
+            return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M:%S')[:6],
+                                     **kwargs)
+
         except ValueError:
             try: # Try without seconds.
-                return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M')[:5])
+                return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M')[:5],
+                                         **kwargs)
             except ValueError: # Try without hour/minutes/seconds.
                 try:
-                    return datetime.datetime(*time.strptime(value, '%Y-%m-%d')[:3])
+                    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 format.')
-
-    def get_db_prep_save(self, value):
-        # Casts dates into string format for entry into database.
-        if value is not None:
-            # MySQL will throw a warning if microseconds are given, because it
-            # doesn't support microseconds.
-            if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
-                value = value.replace(microsecond=0)
-            value = smart_unicode(value)
-        return Field.get_db_prep_save(self, value)
-
-    def get_db_prep_lookup(self, lookup_type, value):
-        if lookup_type == 'range':
-            value = [smart_unicode(v) for v in value]
-        else:
-            value = smart_unicode(value)
-        return Field.get_db_prep_lookup(self, lookup_type, value)
+                    raise exceptions.ValidationError(
+                        _('Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.'))
 
-    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_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_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]
+    def value_to_string(self, obj):
+        val = self._get_val_from_obj(obj)
+        if val is None:
+            data = ''
         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):
-        val = self._get_val_from_obj(obj)
-        date_field, time_field = self.get_manipulator_field_names('')
-        return {date_field: (val is not None and val.strftime("%Y-%m-%d") or ''),
-                time_field: (val is not None and val.strftime("%H:%M:%S") or '')}
+            d = datetime_safe.new_datetime(val)
+            data = d.strftime('%Y-%m-%d %H:%M:%S')
+        return data
 
     def formfield(self, **kwargs):
         defaults = {'form_class': forms.DateTimeField}
@@ -685,11 +582,11 @@
         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):
-        if isinstance(value, basestring):
+        if isinstance(value, basestring) or value is None:
             return value
         else:
             return self.format_number(value)
@@ -699,30 +596,18 @@
         Formats a number into a string with the requisite number of digits and
         decimal places.
         """
-        num_chars = self.max_digits
-        # Allow for a decimal point
-        if self.decimal_places > 0:
-            num_chars += 1
-        # Allow for a minus sign
-        if value < 0:
-            num_chars += 1
-
-        return u"%.*f" % (self.decimal_places, value)
+        # Method moved to django.db.backends.util.
+        #
+        # It is preserved because it is used by the oracle backend
+        # (django.db.backends.oracle.query), and also for
+        # backwards-compatibility with any external code which may have used
+        # this method.
+        from django.db.backends import util
+        return util.format_number(value, self.max_digits, self.decimal_places)
 
-    def get_db_prep_save(self, value):
-        if value is not None:
-            value = self._format(value)
-        return super(DecimalField, self).get_db_prep_save(value)
-
-    def get_db_prep_lookup(self, lookup_type, value):
-        if lookup_type == 'range':
-            value = [self._format(v) for v in value]
-        else:
-            value = self._format(value)
-        return super(DecimalField, self).get_db_prep_lookup(lookup_type, value)
-
-    def get_manipulator_field_objs(self):
-        return [curry(oldforms.DecimalField, max_digits=self.max_digits, decimal_places=self.decimal_places)]
+    def get_db_prep_value(self, value):
+        return connection.ops.value_to_db_decimal(self.to_python(value),
+                self.max_digits, self.decimal_places)
 
     def formfield(self, **kwargs):
         defaults = {
@@ -738,132 +623,17 @@
         kwargs['max_length'] = kwargs.get('max_length', 75)
         CharField.__init__(self, *args, **kwargs)
 
-    def get_manipulator_field_objs(self):
-        return [oldforms.EmailField]
-
-    def validate(self, field_data, all_data):
-        validators.isValidEmail(field_data, all_data)
-
     def formfield(self, **kwargs):
         defaults = {'form_class': forms.EmailField}
         defaults.update(kwargs)
         return super(EmailField, self).formfield(**defaults)
 
-class FileField(Field):
-    def __init__(self, verbose_name=None, name=None, upload_to='', **kwargs):
-        self.upload_to = upload_to
-        kwargs['max_length'] = kwargs.get('max_length', 100)
-        Field.__init__(self, verbose_name, name, **kwargs)
-
-    def get_internal_type(self):
-        return "FileField"
-
-    def get_db_prep_save(self, value):
-        "Returns field's value prepared for saving into a database."
-        # Need to convert UploadedFile objects provided via a form to unicode for database insertion
-        if value is None:
-            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, 'get_%s_filename' % self.name, curry(cls._get_FIELD_filename, field=self))
-        setattr(cls, 'get_%s_url' % self.name, curry(cls._get_FIELD_url, field=self))
-        setattr(cls, 'get_%s_size' % self.name, curry(cls._get_FIELD_size, field=self))
-        setattr(cls, 'save_%s_file' % self.name, lambda instance, filename, raw_contents, save=True: instance._save_FIELD_file(self, filename, raw_contents, save))
-        dispatcher.connect(self.delete_file, signal=signals.post_delete, sender=cls)
-
-    def delete_file(self, instance):
-        if getattr(instance, self.attname):
-            file_name = getattr(instance, 'get_%s_filename' % self.name)()
-            # If the file exists and no other object of this type references it,
-            # delete it from the filesystem.
-            if os.path.exists(file_name) and \
-                not instance.__class__._default_manager.filter(**{'%s__exact' % self.name: getattr(instance, self.attname)}):
-                os.remove(file_name)
-
-    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]
-        if new_data.get(upload_field_name, False):
-            func = getattr(new_object, 'save_%s_file' % self.name)
-            if rel:
-                func(new_data[upload_field_name][0]["filename"], new_data[upload_field_name][0]["content"], save)
-            else:
-                func(new_data[upload_field_name]["filename"], new_data[upload_field_name]["content"], save)
-
-    def get_directory_name(self):
-        return os.path.normpath(force_unicode(datetime.datetime.now().strftime(smart_str(self.upload_to))))
-
-    def get_filename(self, filename):
-        from django.utils.text import get_valid_filename
-        f = os.path.join(self.get_directory_name(), get_valid_filename(os.path.basename(filename)))
-        return os.path.normpath(f)
-
-    def save_form_data(self, instance, data):
-        from django.newforms.fields import UploadedFile
-        if data and isinstance(data, UploadedFile):
-            getattr(instance, "save_%s_file" % self.name)(data.filename, data.content, save=False)
-
-    def formfield(self, **kwargs):
-        defaults = {'form_class': forms.FileField}
-        # If a file has been provided previously, then the form doesn't require
-        # that a new file is provided this time.
-        # The code to mark the form field as not required is used by
-        # form_for_instance, but can probably be removed once form_for_instance
-        # is gone. ModelForm uses a different method to check for an existing file.
-        if 'initial' in kwargs:
-            defaults['required'] = False
-        defaults.update(kwargs)
-        return super(FileField, self).formfield(**defaults)
-
 class FilePathField(Field):
     def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs):
         self.path, self.match, self.recursive = path, match, recursive
         kwargs['max_length'] = kwargs.get('max_length', 100)
         Field.__init__(self, verbose_name, name, **kwargs)
-    
+
     def formfield(self, **kwargs):
         defaults = {
             'path': self.path,
@@ -874,17 +644,16 @@
         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"
 
 class FloatField(Field):
     empty_strings_allowed = False
 
-    def get_manipulator_field_objs(self):
-        return [oldforms.FloatField]
+    def get_db_prep_value(self, value):
+        if value is None:
+            return None
+        return float(value)
 
     def get_internal_type(self):
         return "FloatField"
@@ -894,51 +663,25 @@
         defaults.update(kwargs)
         return super(FloatField, self).formfield(**defaults)
 
-class ImageField(FileField):
-    def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, **kwargs):
-        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 contribute_to_class(self, cls, name):
-        super(ImageField, self).contribute_to_class(cls, name)
-        # Add get_BLAH_width and get_BLAH_height methods, but only if the
-        # image field doesn't have width and height cache fields.
-        if not self.width_field:
-            setattr(cls, 'get_%s_width' % self.name, curry(cls._get_FIELD_width, field=self))
-        if not self.height_field:
-            setattr(cls, 'get_%s_height' % self.name, curry(cls._get_FIELD_height, field=self))
-
-    def get_internal_type(self):
-        return "ImageField"
-
-    def save_file(self, new_data, new_object, original_object, change, rel, save=True):
-        FileField.save_file(self, new_data, new_object, original_object, change, rel, save)
-        # If the image has height and/or width field(s) and they haven't
-        # changed, set the width and/or height field(s) back to their original
-        # values.
-        if change and (self.width_field or self.height_field) and save:
-            if self.width_field:
-                setattr(new_object, self.width_field, getattr(original_object, self.width_field))
-            if self.height_field:
-                setattr(new_object, self.height_field, getattr(original_object, self.height_field))
-            new_object.save()
-
-    def formfield(self, **kwargs):
-        defaults = {'form_class': forms.ImageField}
-        defaults.update(kwargs)
-        return super(ImageField, self).formfield(**defaults)
-
 class IntegerField(Field):
     empty_strings_allowed = False
-    def get_manipulator_field_objs(self):
-        return [oldforms.IntegerField]
+    def get_db_prep_value(self, value):
+        if value is None:
+            return None
+        return int(value)
 
     def get_internal_type(self):
         return "IntegerField"
 
+    def to_python(self, value):
+        if value is None:
+            return value
+        try:
+            return int(value)
+        except (TypeError, ValueError):
+            raise exceptions.ValidationError(
+                _("This value must be an integer."))
+
     def formfield(self, **kwargs):
         defaults = {'form_class': forms.IntegerField}
         defaults.update(kwargs)
@@ -950,15 +693,9 @@
         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"
 
-    def validate(self, field_data, all_data):
-        validators.isValidIPAddress4(field_data, None)
-
     def formfield(self, **kwargs):
         defaults = {'form_class': forms.IPAddressField}
         defaults.update(kwargs)
@@ -975,39 +712,36 @@
 
     def to_python(self, value):
         if value in (None, True, False): return value
-        if value in ('None'): return None
+        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_manipulator_field_objs(self):
-        return [oldforms.NullBooleanField]
+    def get_db_prep_lookup(self, lookup_type, value):
+        # Special-case handling for filters coming from a web request (e.g. the
+        # admin interface). Only works for scalar values (not lists). If you're
+        # passing in a list, you might as well make things the right type when
+        # constructing the list.
+        if value in ('1', '0'):
+            value = bool(int(value))
+        return super(NullBooleanField, self).get_db_prep_lookup(lookup_type, value)
+
+    def get_db_prep_value(self, value):
+        if value is None:
+            return None
+        return bool(value)
 
     def formfield(self, **kwargs):
-        defaults = {'form_class': forms.NullBooleanField}
+        defaults = {
+            'form_class': forms.NullBooleanField,
+            'required': not self.blank,
+            'label': capfirst(self.verbose_name),
+            'help_text': self.help_text}
         defaults.update(kwargs)
         return super(NullBooleanField, self).formfield(**defaults)
 
-class PhoneNumberField(IntegerField):
-    def get_manipulator_field_objs(self):
-        return [oldforms.PhoneNumberField]
-
-    def get_internal_type(self):
-        return "PhoneNumberField"
-
-    def validate(self, field_data, all_data):
-        validators.isValidPhone(field_data, all_data)
-
-    def formfield(self, **kwargs):
-        from django.contrib.localflavor.us.forms import USPhoneNumberField
-        defaults = {'form_class': USPhoneNumberField}
-        defaults.update(kwargs)
-        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"
 
@@ -1017,9 +751,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"
 
@@ -1031,7 +762,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
@@ -1040,17 +770,16 @@
     def get_internal_type(self):
         return "SlugField"
 
+    def formfield(self, **kwargs):
+        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"
 
@@ -1070,20 +799,36 @@
     def get_internal_type(self):
         return "TimeField"
 
-    def get_db_prep_lookup(self, lookup_type, value):
-        if settings.DATABASE_ENGINE == 'oracle':
-            # Oracle requires a date in order to parse.
-            def prep(value):
-                if isinstance(value, datetime.time):
-                    value = datetime.datetime.combine(datetime.date(1900, 1, 1), value)
-                return smart_unicode(value)
+    def to_python(self, value):
+        if value is None:
+            return None
+        if isinstance(value, datetime.time):
+            return value
+
+        # Attempt to parse a datetime:
+        value = smart_str(value)
+        # split usecs, because they are not recognized by strptime.
+        if '.' in value:
+            try:
+                value, usecs = value.split('.')
+                usecs = int(usecs)
+            except ValueError:
+                raise exceptions.ValidationError(
+                    _('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.'))
         else:
-            prep = smart_unicode
-        if lookup_type == 'range':
-            value = [prep(v) for v in value]
-        else:
-            value = prep(value)
-        return Field.get_db_prep_lookup(self, lookup_type, value)
+            usecs = 0
+        kwargs = {'microsecond': usecs}
+
+        try: # Seconds are optional, so try converting seconds first.
+            return datetime.time(*time.strptime(value, '%H:%M:%S')[3:6],
+                                 **kwargs)
+        except ValueError:
+            try: # Try without seconds.
+                return datetime.time(*time.strptime(value, '%H:%M')[3:5],
+                                         **kwargs)
+            except ValueError:
+                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):
@@ -1093,30 +838,17 @@
         else:
             return super(TimeField, self).pre_save(model_instance, add)
 
-    def get_db_prep_save(self, value):
-        # Casts dates into string format for entry into database.
-        if value is not None:
-            # MySQL will throw a warning if microseconds are given, because it
-            # doesn't support microseconds.
-            if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
-                value = value.replace(microsecond=0)
-            if settings.DATABASE_ENGINE == 'oracle':
-                # cx_Oracle expects a datetime.datetime to persist into TIMESTAMP field.
-                if isinstance(value, datetime.time):
-                    value = datetime.datetime(1900, 1, 1, value.hour, value.minute,
-                                              value.second, value.microsecond)
-                elif isinstance(value, basestring):
-                    value = datetime.datetime(*(time.strptime(value, '%H:%M:%S')[:6]))
-            else:
-                value = smart_unicode(value)
-        return Field.get_db_prep_save(self, value)
+    def get_db_prep_value(self, value):
+        # 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}
@@ -1126,46 +858,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"
-
-    def formfield(self, **kwargs):
-        from django.contrib.localflavor.us.forms import USStateSelect
-        defaults = {'widget': USStateSelect}
-        defaults.update(kwargs)
-        return super(USStateField, self).formfield(**defaults)
-
 class XMLField(TextField):
     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)]
-
-class OrderingField(IntegerField):
-    empty_strings_allowed=False
-    def __init__(self, with_respect_to, **kwargs):
-        self.wrt = with_respect_to
-        kwargs['null'] = True
-        IntegerField.__init__(self, **kwargs )
-
-    def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True):
-        return [oldforms.HiddenField(name_prefix + self.name)]