Index: django/db/models/fields/__init__.py
===================================================================
--- django/db/models/fields/__init__.py	(revision 9111)
+++ django/db/models/fields/__init__.py	(working copy)
@@ -313,9 +313,12 @@
             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
+            if form_class in (forms.CharField, forms.BooleanField,forms.IntegerField, forms.RegexField, 
+                              forms.TypedChoiceField, forms.NullBooleanField):
+                 form_class = forms.TypedChoiceField
+                 if self.null:
+                    defaults['empty_value'] = None
+            #else:
             # 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.
Index: tests/regressiontests/forms/tests.py
===================================================================
--- tests/regressiontests/forms/tests.py	(revision 9111)
+++ tests/regressiontests/forms/tests.py	(working copy)
@@ -30,6 +30,7 @@
 from widgets import tests as widgets_tests
 from formsets import tests as formset_tests
 from media import media_tests
+from forms import custom_form_field_tests
 
 __test__ = {
     'extra_tests': extra_tests,
@@ -63,6 +64,7 @@
     'media_tests': media_tests,
     'util_tests': util_tests,
     'widgets_tests': widgets_tests,
+    'custom_form_field_tests': custom_form_field_tests,
 }
 
 if __name__ == "__main__":
Index: tests/regressiontests/forms/models.py
===================================================================
--- tests/regressiontests/forms/models.py	(revision 9111)
+++ tests/regressiontests/forms/models.py	(working copy)
@@ -5,6 +5,7 @@
 # Can't import as "forms" due to implementation details in the test suite (the
 # current file is called "forms" and is already imported).
 from django import forms as django_forms
+from django.utils.encoding import force_unicode
 
 class BoundaryModel(models.Model):
     positive_integer = models.PositiveIntegerField(null=True, blank=True)
@@ -24,6 +25,71 @@
 class FileForm(django_forms.Form):
     file1 = django_forms.FileField()
 
+# models for custom form fields, regress for #9245
+from django.forms import fields
+class CustomFormField(fields.TypedChoiceField):
+    def __init__(self, *args, **kwargs):
+        super(CustomFormField, self).__init__(*args, **kwargs)
+
+    def clean(self, value):
+        return super(CustomFormField, self).clean(value)
+
+# a trivial object to be stored in db
+class Small(object):
+    def __init__(self, first, second):
+        self.first, self.second = first, second
+
+    def __unicode__(self):
+        return u'%s%s' % (force_unicode(self.first), force_unicode(self.second))
+
+    def __str__(self):
+        return unicode(self).encode('utf-8')
+
+# create a custom field upon 'Small' and associate with a custom form field
+class SmallField(models.Field):
+    __metaclass__ = models.SubfieldBase
+
+    def __init__(self, *args, **kwargs):
+        kwargs['max_length'] = 2
+        super(SmallField, self).__init__(*args, **kwargs)
+
+    def get_internal_type(self):
+        return 'CharField'
+
+    def to_python(self, value):
+        if isinstance(value, Small):
+            return value
+        return Small(value[0], value[1])
+
+    def get_db_prep_save(self, value):
+        return unicode(value)
+
+    def get_db_prep_lookup(self, lookup_type, value):
+        if lookup_type == 'exact':
+            return force_unicode(value)
+        if lookup_type == 'in':
+            return [force_unicode(v) for v in value]
+        if lookup_type == 'isnull':
+            return []
+        raise FieldError('Invalid lookup type: %r' % lookup_type)
+
+    def formfield(self, **kwargs):
+        return super(SmallField, self).formfield(form_class = CustomFormField, **kwargs)
+        return super(SmallField, self).formfield(**kwargs)
+
+# use SmallField in a model
+class MyModel(models.Model):
+    name = models.CharField(max_length=10)
+    MY_CHOICES  = (
+        ('AB', 'ab'),
+        ('CD', 'cd'),
+        ('EF', 'ef'),
+    )
+    data = SmallField('small field',choices = MY_CHOICES)
+
+    def __unicode__(self):
+        return force_unicode(self.name)
+
 __test__ = {'API_TESTS': """
 >>> from django.forms.models import ModelForm
 >>> from django.core.files.uploadedfile import SimpleUploadedFile
Index: tests/regressiontests/forms/forms.py
===================================================================
--- tests/regressiontests/forms/forms.py	(revision 9111)
+++ tests/regressiontests/forms/forms.py	(working copy)
@@ -1750,3 +1750,38 @@
 True
 
 """
+# -*- coding: utf-8 -*-
+custom_form_field_tests = r"""
+>>> from regressiontests.forms.models import MyModel
+>>> from regressiontests.forms.models import Small
+>>> s = Small('A', 'B')
+>>> MyModel.objects.create(pk=1, name='abc', data = s)
+<MyModel: abc>
+>>> from django.forms import ModelForm
+>>> class MyModelForm(ModelForm):
+...     class Meta:
+...         model = MyModel
+... 
+>>> mymodel_form = MyModelForm(instance = MyModel.objects.get(id=1))
+>>> print mymodel_form['data']
+<select name="data" id="id_data">
+<option value="">---------</option>
+<option value="AB" selected="selected">ab</option>
+<option value="CD">cd</option>
+<option value="EF">ef</option>
+</select>
+>>> from regressiontests.forms.models import SmallField
+>>> small_field = SmallField('a simple small field', choices = MyModel.MY_CHOICES)
+>>> small_field.formfield().__class__
+<class 'regressiontests.forms.models.CustomFormField'>
+>>> small_field = SmallField('small field without choices')
+>>> small_field.formfield().__class__
+<class 'regressiontests.forms.models.CustomFormField'>
+>>> from django.db import models
+>>> regular_field = models.CharField(max_length=2, choices = MyModel.MY_CHOICES)
+>>> regular_field.formfield().__class__
+<class 'django.forms.fields.TypedChoiceField'>
+>>> regular_field = models.CharField(max_length=10)
+>>> regular_field.formfield().__class__
+<class 'django.forms.fields.CharField'>
+"""
