diff --git a/django/forms/fields.py b/django/forms/fields.py
index 621d380..d7b6ebb 100644
--- a/django/forms/fields.py
+++ b/django/forms/fields.py
@@ -743,6 +743,15 @@ class NullBooleanField(BooleanField):
         return initial != data
 
 
+class CallableChoiceIterator(object):
+    def __init__(self, callme, field):
+        self.callme = callme
+        self.field = field
+
+    def __iter__(self):
+        for e in self.callme(self.field):
+            yield e
+
 class ChoiceField(Field):
     widget = Select
     default_error_messages = {
@@ -757,7 +766,7 @@ class ChoiceField(Field):
 
     def __deepcopy__(self, memo):
         result = super(ChoiceField, self).__deepcopy__(memo)
-        result._choices = copy.deepcopy(self._choices, memo)
+        result._set_choices(copy.deepcopy(self._choices, memo))
         return result
 
     def _get_choices(self):
@@ -765,9 +774,14 @@ class ChoiceField(Field):
 
     def _set_choices(self, value):
         # Setting choices also sets the choices on the widget.
-        # choices can be any iterable, but we call list() on it because
-        # it will be consumed more than once.
-        self._choices = self.widget.choices = list(value)
+        if callable(value):
+            value = CallableChoiceIterator(value, self)
+        else:
+            # choices can be any iterable, but we call list() on it because
+            # it will be consumed more than once.
+            value = list(value)
+
+        self._choices = self.widget.choices = value
 
     choices = property(_get_choices, _set_choices)
 
diff --git a/tests/regressiontests/forms/tests/fields.py b/tests/regressiontests/forms/tests/fields.py
index 3fe2cd2..bdce0ba 100644
--- a/tests/regressiontests/forms/tests/fields.py
+++ b/tests/regressiontests/forms/tests/fields.py
@@ -49,7 +49,6 @@ def fix_os_paths(x):
     else:
         return x
 
-
 class FieldsTests(SimpleTestCase):
 
     def assertWidgetRendersTo(self, field, to):
@@ -893,6 +892,27 @@ class FieldsTests(SimpleTestCase):
         f = TypedChoiceField(choices=[(1, "+1"), (-1, "-1")], coerce=int, required=False, empty_value=None)
         self.assertEqual(None, f.clean(''))
 
+    def test_choicefield_callable(self):
+        choices = lambda field: [('J', 'John'), ('P', 'Paul')]
+        f = ChoiceField(choices=choices)
+        self.assertEqual(u'J', f.clean('J'))
+      
+    def test_choicefield_callable_may_evaluate_to_different_values(self):
+        choices = []
+        def choices_as_callable(field):
+            return choices
+
+        class ChoiceFieldForm(Form):
+            choicefield = ChoiceField(choices=choices_as_callable)
+
+        choices = [('J', 'John'), ('P', 'Paul')]
+        form = ChoiceFieldForm()
+        self.assertTrue("John" in form.as_p())
+
+        choices = [('M', 'Marie'),]
+        form = ChoiceFieldForm()
+        self.assertTrue("Marie" in form.as_p())
+
     # NullBooleanField ############################################################
 
     def test_nullbooleanfield_1(self):
