Index: /store/django_no_magic/django/db/models/fields/__init__.py
===================================================================
--- /store/django_no_magic/django/db/models/fields/__init__.py	(revision 2602)
+++ /store/django_no_magic/django/db/models/fields/__init__.py	(working copy)
@@ -112,6 +112,9 @@
         """
         if not self.blank and not field_data:
             return [gettext_lazy('This field is required.')]
+        # XXX IMHO this is the place for NULL validation, to_python will return '' (blank) or None as appropriate
+        if not self.null and field_data is None:
+            return [gettext_lazy('This field is required.')]
         try:
             self.validate(field_data, all_data)
         except validators.ValidationError, e:
@@ -331,6 +334,8 @@
     def __init__(self, *args, **kwargs):
         assert kwargs.get('primary_key', False) is True, "%ss must have primary_key=True." % self.__class__.__name__
         kwargs['blank'] = True
+        # added because validators
+        kwargs['null'] = True
         Field.__init__(self, *args, **kwargs)
 
     def to_python(self, value):
@@ -368,7 +373,10 @@
         Field.__init__(self, *args, **kwargs)
 
     def to_python(self, value):
+        if value is None:
+            raise validators.ValidationError, gettext("This value can not be None.")
         if value in (True, False): return value
+        if value == '': return False
         if value is 't': return True
         if value is 'f': return False
         raise validators.ValidationError, gettext("This value must be either True or False.")
@@ -383,12 +391,13 @@
     def to_python(self, value):
         if isinstance(value, basestring):
             return value
-        if value is None:
-            if self.null:
-                return value
-            else:
-                raise validators.ValidationError, gettext_lazy("This field cannot be null.")
+        if value is None: return value
         return str(value)
+    
+    def validate(self, field_data, all_data):
+        if not field_data: return
+        if self.maxlength < len(field_data):
+            raise validators.ValidationError, gettext_lazy("Maximum string length exceeded.")
 
 # TODO: Maybe move this into contrib, because it's specialized.
 class CommaSeparatedIntegerField(CharField):
@@ -395,6 +404,21 @@
     def get_manipulator_field_objs(self):
         return [forms.CommaSeparatedIntegerField]
 
+    def to_python(self, value):
+        value = super(CommaSeparatedIntegerField, self).to_python(value)
+        if not value: return []
+        try:
+            return [int(l) for l in value.split(',')]
+        except (TypeError, ValueError):
+            raise ValidationError, gettext("Enter a whole number.")
+
+    def validate(self, field_data, all_data):
+        if not field_data: return
+        # XXX hmmm, I presume that maxlength here means the maximum entries
+        if self.maxlength < len(field_data):
+            raise validators.ValidationError, gettext_lazy("Exceeded maximum number of entries.")
+
+
 class DateField(Field):
     empty_strings_allowed = False
     def __init__(self, verbose_name=None, name=None, auto_now=False, auto_now_add=False, **kwargs):
@@ -406,6 +430,7 @@
         Field.__init__(self, verbose_name, name, **kwargs)
 
     def to_python(self, value):
+        if value is None or value == '': return None
         if isinstance(value, datetime.datetime):
             return value.date()
         if isinstance(value, datetime.date):
@@ -457,6 +482,7 @@
 
 class DateTimeField(DateField):
     def to_python(self, value):
+        if value is None or value == '': return None
         if isinstance(value, datetime.datetime):
             return value
         if isinstance(value, datetime.date):
@@ -625,6 +651,18 @@
     def get_manipulator_field_objs(self):
         return [curry(forms.FloatField, max_digits=self.max_digits, decimal_places=self.decimal_places)]
 
+    def to_python(self, value):
+        import decimal
+        if value is None or value == '': return None
+        try:
+            return decimal.Decimal(value)
+        except (TypeError, ValueError):
+            raise validators.ValidationError, gettext_lazy("Enter a float number.")
+
+    def validate(self, field_data, all_data):
+        if len('%.0f' % abs(field_data)) > self.max_digits:
+            raise validators.ValidationError, gettext_lazy("Too many digits.")
+
 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
@@ -659,6 +697,13 @@
     def get_manipulator_field_objs(self):
         return [forms.IntegerField]
 
+    def to_python(self, value):
+        if value is None or value == '': return None
+        try:
+            return int(value)
+        except (TypeError, ValueError):
+            raise validators.ValidationError, gettext_lazy("Enter a whole number.")
+
 class IPAddressField(Field):
     def __init__(self, *args, **kwargs):
         kwargs['maxlength'] = 15
@@ -678,6 +723,13 @@
     def get_manipulator_field_objs(self):
         return [forms.NullBooleanField]
 
+    def to_python(self, value):
+        if value is None or value == '': return None
+        if value in (True, False): return value
+        if value is 't': return True
+        if value is 'f': return False
+        raise validators.ValidationError, gettext("This value must be either True or False.")
+
 class PhoneNumberField(IntegerField):
     def get_manipulator_field_objs(self):
         return [forms.PhoneNumberField]
@@ -689,6 +741,17 @@
     def get_manipulator_field_objs(self):
         return [forms.PositiveIntegerField]
 
+    def to_python(self, value):
+        if value is None or value == '': return None
+        try:
+            return int(value)
+        except (TypeError, ValueError):
+            raise validators.ValidationError, gettext_lazy("Enter a whole number.")
+
+    def validate(self, field_data, all_data):
+        if field_data < 0:
+            raise validators.ValidationError, gettext_lazy("Enter a whole positive number.")
+
 class PositiveSmallIntegerField(IntegerField):
     def get_manipulator_field_objs(self):
         return [forms.PositiveSmallIntegerField]
@@ -693,6 +756,17 @@
     def get_manipulator_field_objs(self):
         return [forms.PositiveSmallIntegerField]
 
+    def to_python(self, value):
+        if value is None or value == '': return None
+        try:
+            return int(value)
+        except (TypeError, ValueError):
+            raise validators.ValidationError, gettext_lazy("Enter a whole number.")
+
+    def validate(self, field_data, all_data):
+        if field_data < 0:
+            raise validators.ValidationError, gettext_lazy("Enter a whole positive number.")
+
 class SlugField(Field):
     def __init__(self, *args, **kwargs):
         kwargs['maxlength'] = 50
@@ -705,6 +779,9 @@
     def get_manipulator_field_objs(self):
         return [forms.TextField]
 
+    def validate(self, field_data, all_data):
+        validators.isSlug(field_data, all_data)
+
 class SmallIntegerField(IntegerField):
     def get_manipulator_field_objs(self):
         return [forms.SmallIntegerField]
@@ -709,6 +786,13 @@
     def get_manipulator_field_objs(self):
         return [forms.SmallIntegerField]
 
+    def to_python(self, value):
+        if value is None or value == '': return None
+        try:
+            return int(value)
+        except (TypeError, ValueError):
+            raise validators.ValidationError, gettext_lazy("Enter a whole number.")
+
 class TextField(Field):
     def get_manipulator_field_objs(self):
         return [forms.LargeTextField]
@@ -750,6 +834,14 @@
         val = self._get_val_from_obj(obj)
         return {self.attname: (val is not None and val.strftime("%H:%M:%S") or '')}
 
+    def to_python(self, value):
+        if value is None or value == '': return None
+        try:
+            st = time.strptime(value, '%H:%M:%S')
+            return datetime.time(st.tm_hour, st.tm_min, st.tm_sec)
+        except (TypeError, ValueError):
+            raise validators.ValidationError, gettext_lazy("Enter a whole number.")
+
 class URLField(Field):
     def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs):
         if verify_exists:
@@ -754,6 +846,7 @@
     def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs):
         if verify_exists:
             kwargs.setdefault('validator_list', []).append(validators.isExistingURL)
+        self.verify_exists = verify_exists
         Field.__init__(self, verbose_name, name, **kwargs)
 
     def get_manipulator_field_objs(self):
@@ -759,6 +852,16 @@
     def get_manipulator_field_objs(self):
         return [forms.URLField]
 
+    def to_python(self, value):
+        if isinstance(value, basestring): return value
+        if value is None: return value
+        return str(value)
+    
+    def validate(self, field_data, all_data):
+        validators.isValidURL(field_data, all_data)
+        if self.verify_exists:
+            validators.isExistingURL(field_data, all_data)
+
 class USStateField(Field):
     def get_manipulator_field_objs(self):
         return [forms.USStateField]
