Ticket #13181: with_field_as_param.diff

File with_field_as_param.diff, 3.0 KB (added by Klaas van Schelven, 10 years ago)
  • django/forms/fields.py

    diff --git a/django/forms/fields.py b/django/forms/fields.py
    index 621d380..d7b6ebb 100644
    a b class NullBooleanField(BooleanField): 
    743743        return initial != data
    744744
    745745
     746class CallableChoiceIterator(object):
     747    def __init__(self, callme, field):
     748        self.callme = callme
     749        self.field = field
     750
     751    def __iter__(self):
     752        for e in self.callme(self.field):
     753            yield e
     754
    746755class ChoiceField(Field):
    747756    widget = Select
    748757    default_error_messages = {
    class ChoiceField(Field): 
    757766
    758767    def __deepcopy__(self, memo):
    759768        result = super(ChoiceField, self).__deepcopy__(memo)
    760         result._choices = copy.deepcopy(self._choices, memo)
     769        result._set_choices(copy.deepcopy(self._choices, memo))
    761770        return result
    762771
    763772    def _get_choices(self):
    class ChoiceField(Field): 
    765774
    766775    def _set_choices(self, value):
    767776        # Setting choices also sets the choices on the widget.
    768         # choices can be any iterable, but we call list() on it because
    769         # it will be consumed more than once.
    770         self._choices = self.widget.choices = list(value)
     777        if callable(value):
     778            value = CallableChoiceIterator(value, self)
     779        else:
     780            # choices can be any iterable, but we call list() on it because
     781            # it will be consumed more than once.
     782            value = list(value)
     783
     784        self._choices = self.widget.choices = value
    771785
    772786    choices = property(_get_choices, _set_choices)
    773787
  • tests/regressiontests/forms/tests/fields.py

    diff --git a/tests/regressiontests/forms/tests/fields.py b/tests/regressiontests/forms/tests/fields.py
    index 3fe2cd2..bdce0ba 100644
    a b def fix_os_paths(x): 
    4949    else:
    5050        return x
    5151
    52 
    5352class FieldsTests(SimpleTestCase):
    5453
    5554    def assertWidgetRendersTo(self, field, to):
    class FieldsTests(SimpleTestCase): 
    893892        f = TypedChoiceField(choices=[(1, "+1"), (-1, "-1")], coerce=int, required=False, empty_value=None)
    894893        self.assertEqual(None, f.clean(''))
    895894
     895    def test_choicefield_callable(self):
     896        choices = lambda field: [('J', 'John'), ('P', 'Paul')]
     897        f = ChoiceField(choices=choices)
     898        self.assertEqual(u'J', f.clean('J'))
     899     
     900    def test_choicefield_callable_may_evaluate_to_different_values(self):
     901        choices = []
     902        def choices_as_callable(field):
     903            return choices
     904
     905        class ChoiceFieldForm(Form):
     906            choicefield = ChoiceField(choices=choices_as_callable)
     907
     908        choices = [('J', 'John'), ('P', 'Paul')]
     909        form = ChoiceFieldForm()
     910        self.assertTrue("John" in form.as_p())
     911
     912        choices = [('M', 'Marie'),]
     913        form = ChoiceFieldForm()
     914        self.assertTrue("Marie" in form.as_p())
     915
    896916    # NullBooleanField ############################################################
    897917
    898918    def test_nullbooleanfield_1(self):
Back to Top