Index: tests/regressiontests/model_fields/tests.py
===================================================================
diff --git a/django/trunk/tests/regressiontests/model_fields/tests.py b/django/trunk/tests/regressiontests/model_fields/tests.py
--- a/django/trunk/tests/regressiontests/model_fields/tests.py	(revision 17708)
+++ b/django/trunk/tests/regressiontests/model_fields/tests.py	(working copy)
@@ -11,7 +11,8 @@
 from django.utils import unittest
 
 from .models import (Foo, Bar, Whiz, BigD, BigS, Image, BigInt, Post,
-    NullBooleanModel, BooleanModel, Document, RenamedField)
+    NullBooleanModel, BooleanModel, Document, RenamedField,
+    CustomIntegerFormField)
 
 # If PIL available, do these tests.
 if Image:
@@ -223,6 +224,16 @@
         self.assertEqual(Whiz(c=None).get_c_display(), None)    # Blank value
         self.assertEqual(Whiz(c='').get_c_display(), '')        # Empty value
 
+    def test_choices_formfield_overrides(self):
+        whiz_meta = Whiz(c=1)._meta
+        field = whiz_meta.get_field_by_name('c')[0]
+        self.assertIs(type(field.formfield()),
+                forms.TypedChoiceField)
+        self.assertIs(type(whiz_meta.get_field_by_name('d')[0].formfield()),
+                CustomIntegerFormField)
+        self.assertIs(type(whiz_meta.get_field_by_name('ts')[0].formfield()),
+                forms.DateTimeField)
+
 class SlugFieldTests(test.TestCase):
     def test_slugfield_max_length(self):
         """
Index: tests/regressiontests/model_fields/models.py
===================================================================
diff --git a/django/trunk/tests/regressiontests/model_fields/models.py b/django/trunk/tests/regressiontests/model_fields/models.py
--- a/django/trunk/tests/regressiontests/model_fields/models.py	(revision 17708)
+++ b/django/trunk/tests/regressiontests/model_fields/models.py	(working copy)
@@ -13,6 +13,7 @@
     except ImportError:
         Image = None
 
+from django import forms
 from django.core.files.storage import FileSystemStorage
 from django.db import models
 from django.db.models.fields.files import ImageFieldFile, ImageField
@@ -29,6 +30,18 @@
     b = models.CharField(max_length=10)
     a = models.ForeignKey(Foo, default=get_foo)
 
+class CustomIntegerFormField(forms.IntegerField):
+    def __init__(self, *args, **kwargs):
+        if 'choices' in kwargs:
+            del kwargs['choices']
+        super(CustomIntegerFormField, self).__init__(*args, **kwargs)
+
+class CustomIntegerField(models.IntegerField):
+    def formfield(self, **kwargs):
+        if 'form_class' not in kwargs:
+            kwargs['form_class'] = CustomIntegerFormField
+        return super(CustomIntegerField, self).formfield(**kwargs)
+
 class Whiz(models.Model):
     CHOICES = (
         ('Group 1', (
@@ -44,6 +57,8 @@
         (0,'Other'),
     )
     c = models.IntegerField(choices=CHOICES, null=True)
+    d = CustomIntegerField(choices=CHOICES, default=4)
+    ts = models.DateTimeField(auto_now_add=True)
 
 class BigD(models.Model):
     d = models.DecimalField(max_digits=38, decimal_places=30)
Index: django/db/models/fields/__init__.py
===================================================================
diff --git a/django/trunk/django/db/models/fields/__init__.py b/django/trunk/django/db/models/fields/__init__.py
--- a/django/trunk/django/db/models/fields/__init__.py	(revision 17708)
+++ b/django/trunk/django/db/models/fields/__init__.py	(working copy)
@@ -453,7 +453,7 @@
     def save_form_data(self, instance, data):
         setattr(instance, self.name, data)
 
-    def formfield(self, form_class=forms.CharField, **kwargs):
+    def formfield(self, form_class=None, **kwargs):
         """
         Returns a django.forms.Field instance for this database Field.
         """
@@ -471,18 +471,21 @@
             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', 'show_hidden_initial'):
-                    del kwargs[k]
+            if not form_class:
+                form_class = forms.TypedChoiceField
+                defaults['coerce'] = self.to_python
+                if self.null:
+                    defaults['empty_value'] = None
+                # 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', 'show_hidden_initial'):
+                        del kwargs[k]
+        if not form_class:
+            form_class = forms.CharField
         defaults.update(kwargs)
         return form_class(**defaults)
 
@@ -722,8 +725,11 @@
         return '' if val is None else val.isoformat()
 
     def formfield(self, **kwargs):
-        defaults = {'form_class': forms.DateField}
-        defaults.update(kwargs)
+        if self.choices:
+            defaults = kwargs
+        else:
+            defaults = {'form_class': forms.DateField}
+            defaults.update(kwargs)
         return super(DateField, self).formfield(**defaults)
 
 class DateTimeField(DateField):
@@ -821,8 +827,11 @@
         return '' if val is None else val.isoformat()
 
     def formfield(self, **kwargs):
-        defaults = {'form_class': forms.DateTimeField}
-        defaults.update(kwargs)
+        if self.choices:
+            defaults = kwargs
+        else:
+            defaults = {'form_class': forms.DateTimeField}
+            defaults.update(kwargs)
         return super(DateTimeField, self).formfield(**defaults)
 
 class DecimalField(Field):
@@ -949,8 +958,11 @@
             raise exceptions.ValidationError(msg)
 
     def formfield(self, **kwargs):
-        defaults = {'form_class': forms.FloatField}
-        defaults.update(kwargs)
+        if self.choices:
+            defaults = kwargs
+        else:
+            defaults = {'form_class': forms.FloatField}
+            defaults.update(kwargs)
         return super(FloatField, self).formfield(**defaults)
 
 class IntegerField(Field):
@@ -984,8 +996,11 @@
             raise exceptions.ValidationError(msg)
 
     def formfield(self, **kwargs):
-        defaults = {'form_class': forms.IntegerField}
-        defaults.update(kwargs)
+        if self.choices:
+            defaults = kwargs
+        else:
+            defaults = {'form_class': forms.IntegerField}
+            defaults.update(kwargs)
         return super(IntegerField, self).formfield(**defaults)
 
 class BigIntegerField(IntegerField):
@@ -1014,8 +1029,11 @@
         return "IPAddressField"
 
     def formfield(self, **kwargs):
-        defaults = {'form_class': forms.IPAddressField}
-        defaults.update(kwargs)
+        if self.choices:
+            defaults = kwargs
+        else:
+            defaults = {'form_class': forms.IPAddressField}
+            defaults.update(kwargs)
         return super(IPAddressField, self).formfield(**defaults)
 
 class GenericIPAddressField(Field):
@@ -1054,11 +1072,13 @@
         return value
 
     def formfield(self, **kwargs):
-        defaults = {'form_class': forms.GenericIPAddressField}
-        defaults.update(kwargs)
+        if self.choices:
+            defaults = kwargs
+        else:
+            defaults = {'form_class': forms.GenericIPAddressField}
+            defaults.update(kwargs)
         return super(GenericIPAddressField, self).formfield(**defaults)
 
-
 class NullBooleanField(Field):
     empty_strings_allowed = False
     default_error_messages = {
@@ -1105,11 +1125,12 @@
 
     def formfield(self, **kwargs):
         defaults = {
-            'form_class': forms.NullBooleanField,
             'required': not self.blank,
             'label': capfirst(self.verbose_name),
             'help_text': self.help_text}
         defaults.update(kwargs)
+        if not self.choices:
+            defaults['form_class'] = forms.NullBooleanField
         return super(NullBooleanField, self).formfield(**defaults)
 
 class PositiveIntegerField(IntegerField):
@@ -1148,7 +1169,11 @@
         return "SlugField"
 
     def formfield(self, **kwargs):
-        defaults = {'form_class': forms.SlugField}
+        if self.choices:
+            defaults = kwargs
+        else:
+            defaults = {'form_class': forms.SlugField}
+            defaults.update(kwargs)
         defaults.update(kwargs)
         return super(SlugField, self).formfield(**defaults)
 
@@ -1241,8 +1266,11 @@
         return '' if val is None else val.isoformat()
 
     def formfield(self, **kwargs):
-        defaults = {'form_class': forms.TimeField}
-        defaults.update(kwargs)
+        if self.choices:
+            defaults = kwargs
+        else:
+            defaults = {'form_class': forms.TimeField}
+            defaults.update(kwargs)
         return super(TimeField, self).formfield(**defaults)
 
 class URLField(CharField):
@@ -1258,8 +1286,9 @@
     def formfield(self, **kwargs):
         # As with CharField, this will cause URL validation to be performed
         # twice.
-        defaults = {
-            'form_class': forms.URLField,
-        }
-        defaults.update(kwargs)
+        if self.choices:
+            defaults = kwargs
+        else:
+            defaults = {'form_class': forms.URLField}
+            defaults.update(kwargs)
         return super(URLField, self).formfield(**defaults)
