Ticket #13181: with_callable_choice_iterator.diff

File with_callable_choice_iterator.diff, 2.7 KB (added by Klaas van Schelven, 11 years ago)
  • django/forms/fields.py

    diff --git a/django/forms/fields.py b/django/forms/fields.py
    index 621d380..8794434 100644
    a b class NullBooleanField(BooleanField):  
    743743        return initial != data
    744744
    745745
     746class CallableChoiceIterator(object):
     747    def __init__(self, f):
     748        self.f = f
     749
     750    def __iter__(self):
     751        for e in self.f():
     752            yield e
     753
    746754class ChoiceField(Field):
    747755    widget = Select
    748756    default_error_messages = {
    class ChoiceField(Field):  
    757765
    758766    def __deepcopy__(self, memo):
    759767        result = super(ChoiceField, self).__deepcopy__(memo)
    760         result._choices = copy.deepcopy(self._choices, memo)
     768        result._set_choices(copy.deepcopy(self._choices, memo))
    761769        return result
    762770
    763771    def _get_choices(self):
    class ChoiceField(Field):  
    767775        # Setting choices also sets the choices on the widget.
    768776        # choices can be any iterable, but we call list() on it because
    769777        # it will be consumed more than once.
    770         self._choices = self.widget.choices = list(value)
     778        if callable(value):
     779            value = CallableChoiceIterator(value)
     780        else:
     781            value = list(value)
     782
     783        self._choices = self.widget.choices = value
    771784
    772785    choices = property(_get_choices, _set_choices)
    773786
  • tests/regressiontests/forms/tests/fields.py

    diff --git a/tests/regressiontests/forms/tests/fields.py b/tests/regressiontests/forms/tests/fields.py
    index 3fe2cd2..945a2ae 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: [('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():
     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