diff --git a/django/forms/fields.py b/django/forms/fields.py
index 621d380..a9dca5c 100644
|
a
|
b
|
class ChoiceField(Field):
|
| 757 | 757 | |
| 758 | 758 | def __deepcopy__(self, memo): |
| 759 | 759 | result = super(ChoiceField, self).__deepcopy__(memo) |
| 760 | | result._choices = copy.deepcopy(self._choices, memo) |
| | 760 | |
| | 761 | if hasattr(self, '_choices_as_callable'): |
| | 762 | result_choices = self._choices_as_callable() |
| | 763 | else: |
| | 764 | result_choices = copy.deepcopy(self._choices, memo) |
| | 765 | |
| | 766 | result._set_choices(result_choices) |
| | 767 | |
| 761 | 768 | return result |
| 762 | 769 | |
| 763 | 770 | def _get_choices(self): |
| … |
… |
class ChoiceField(Field):
|
| 767 | 774 | # Setting choices also sets the choices on the widget. |
| 768 | 775 | # choices can be any iterable, but we call list() on it because |
| 769 | 776 | # it will be consumed more than once. |
| 770 | | self._choices = self.widget.choices = list(value) |
| | 777 | if callable(value): |
| | 778 | self._choices = value() |
| | 779 | self._choices_as_callable = value |
| | 780 | else: |
| | 781 | self._choices = self.widget.choices = list(value) |
| | 782 | |
| 771 | 783 | |
| 772 | 784 | choices = property(_get_choices, _set_choices) |
| 773 | 785 | |
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):
|
| 49 | 49 | else: |
| 50 | 50 | return x |
| 51 | 51 | |
| 52 | | |
| 53 | 52 | class FieldsTests(SimpleTestCase): |
| 54 | 53 | |
| 55 | 54 | def assertWidgetRendersTo(self, field, to): |
| … |
… |
class FieldsTests(SimpleTestCase):
|
| 893 | 892 | f = TypedChoiceField(choices=[(1, "+1"), (-1, "-1")], coerce=int, required=False, empty_value=None) |
| 894 | 893 | self.assertEqual(None, f.clean('')) |
| 895 | 894 | |
| | 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 | |
| 896 | 916 | # NullBooleanField ############################################################ |
| 897 | 917 | |
| 898 | 918 | def test_nullbooleanfield_1(self): |