Browse Source

Merge pull request #804 from oinopion/ticket18162

Fixes #18162 --  Specifying choices to Field overrides any form_class argument
Honza Král 12 years ago
parent
commit
10026c2ad0
2 changed files with 15 additions and 2 deletions
  1. 5 2
      django/db/models/fields/__init__.py
  2. 10 0
      tests/regressiontests/model_fields/tests.py

+ 5 - 2
django/db/models/fields/__init__.py

@@ -467,7 +467,7 @@ class Field(object):
     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.
         """
@@ -488,7 +488,8 @@ class Field(object):
             defaults['coerce'] = self.to_python
             if self.null:
                 defaults['empty_value'] = None
-            form_class = forms.TypedChoiceField
+            if form_class is None or not issubclass(form_class, forms.TypedChoiceField):
+                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.
@@ -498,6 +499,8 @@ class Field(object):
                              'error_messages', 'show_hidden_initial'):
                     del kwargs[k]
         defaults.update(kwargs)
+        if form_class is None:
+            form_class = forms.CharField
         return form_class(**defaults)
 
     def value_from_object(self, obj):

+ 10 - 0
tests/regressiontests/model_fields/tests.py

@@ -73,6 +73,16 @@ class BasicFieldTests(test.TestCase):
 
         self.assertEqual(m._meta.get_field('id').verbose_name, 'verbose pk')
 
+    def test_formclass_with_choices(self):
+        # regression for 18162
+        class CustomChoiceField(forms.TypedChoiceField):
+            pass
+        choices = [('a@b.cc', 'a@b.cc'), ('b@b.cc', 'b@b.cc')]
+        field = models.CharField(choices=choices)
+        klass = CustomChoiceField
+        self.assertIsInstance(field.formfield(form_class=klass), klass)
+
+
 class DecimalFieldTests(test.TestCase):
     def test_to_python(self):
         f = models.DecimalField(max_digits=4, decimal_places=2)