Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

[1.6.x] Fixed #20999 - Allow overriding formfield class with choices,…

… without subclass restrictions.

Refs #18162. Thanks claudep and mjtamlyn for review.

Backport of 7211741 from master.
  • Loading branch information...
commit 21a3efcf48559b3336ca1743d94c741a82feffd6 1 parent 1d874ce
Carl Meyer authored August 29, 2013
6  django/db/models/fields/__init__.py
@@ -515,7 +515,7 @@ def _get_flatchoices(self):
515 515
     def save_form_data(self, instance, data):
516 516
         setattr(instance, self.name, data)
517 517
 
518  
-    def formfield(self, form_class=None, **kwargs):
  518
+    def formfield(self, form_class=None, choices_form_class=None, **kwargs):
519 519
         """
520 520
         Returns a django.forms.Field instance for this database Field.
521 521
         """
@@ -536,7 +536,9 @@ def formfield(self, form_class=None, **kwargs):
536 536
             defaults['coerce'] = self.to_python
537 537
             if self.null:
538 538
                 defaults['empty_value'] = None
539  
-            if form_class is None or not issubclass(form_class, forms.TypedChoiceField):
  539
+            if choices_form_class is not None:
  540
+                form_class = choices_form_class
  541
+            else:
540 542
                 form_class = forms.TypedChoiceField
541 543
             # Many of the subclass-specific formfield arguments (min_value,
542 544
             # max_value) don't apply for choice fields, so be sure to only pass
20  docs/howto/custom-model-fields.txt
@@ -617,17 +617,23 @@ prepared with :meth:`.get_prep_lookup`.
617 617
 Specifying the form field for a model field
618 618
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
619 619
 
620  
-.. method:: Field.formfield(self, form_class=forms.CharField, **kwargs)
  620
+.. method:: Field.formfield(self, form_class=None, choices_form_class=None, **kwargs)
621 621
 
622  
-Returns the default form field to use when this field is displayed in a model.
623  
-This method is called by the :class:`~django.forms.ModelForm` helper.
  622
+Returns the default form field to use when this model field is displayed in a
  623
+form.  This method is called by the :class:`~django.forms.ModelForm` helper.
  624
+
  625
+The form field class can be specified via the ``form_class`` and
  626
+``choices_form_class`` arguments; the latter is used if the field has choices
  627
+specified, the former otherwise. If these arguments are not provided,
  628
+:class:`~django.forms.CharField` or :class:`~django.forms.TypedChoiceField`
  629
+will be used.
624 630
 
625 631
 All of the ``kwargs`` dictionary is passed directly to the form field's
626 632
 ``__init__()`` method. Normally, all you need to do is set up a good default
627  
-for the ``form_class`` argument and then delegate further handling to the
628  
-parent class. This might require you to write a custom form field (and even a
629  
-form widget). See the :doc:`forms documentation </topics/forms/index>` for
630  
-information about this.
  633
+for the ``form_class`` (and maybe ``choices_form_class``) argument and then
  634
+delegate further handling to the parent class. This might require you to write
  635
+a custom form field (and even a form widget). See the :doc:`forms documentation
  636
+</topics/forms/index>` for information about this.
631 637
 
632 638
 Continuing our ongoing example, we can write the :meth:`.formfield` method as::
633 639
 
12  tests/model_fields/tests.py
@@ -68,14 +68,12 @@ def test_field_verbose_name(self):
68 68
 
69 69
         self.assertEqual(m._meta.get_field('id').verbose_name, 'verbose pk')
70 70
 
71  
-    def test_formclass_with_choices(self):
72  
-        # regression for 18162
73  
-        class CustomChoiceField(forms.TypedChoiceField):
74  
-            pass
75  
-        choices = [('a@b.cc', 'a@b.cc'), ('b@b.cc', 'b@b.cc')]
  71
+    def test_choices_form_class(self):
  72
+        """Can supply a custom choices form class. Regression for #20999."""
  73
+        choices = [('a', 'a')]
76 74
         field = models.CharField(choices=choices)
77  
-        klass = CustomChoiceField
78  
-        self.assertIsInstance(field.formfield(form_class=klass), klass)
  75
+        klass = forms.TypedMultipleChoiceField
  76
+        self.assertIsInstance(field.formfield(choices_form_class=klass), klass)
79 77
 
80 78
 
81 79
 class DecimalFieldTests(test.TestCase):

0 notes on commit 21a3efc

Please sign in to comment.
Something went wrong with that request. Please try again.