diff --git a/django/forms/fields.py b/django/forms/fields.py index 9f85f96dd0..d9552c28fe 100644 --- a/django/forms/fields.py +++ b/django/forms/fields.py @@ -94,6 +94,8 @@ class Field(object): widget = widget or self.widget if isinstance(widget, type): widget = widget() + else: + widget = copy.deepcopy(widget) # Trigger the localization machinery if needed. self.localize = localize diff --git a/tests/forms_tests/field_tests/test_base.py b/tests/forms_tests/field_tests/test_base.py index 2eea92a149..802af3b183 100644 --- a/tests/forms_tests/field_tests/test_base.py +++ b/tests/forms_tests/field_tests/test_base.py @@ -1,4 +1,4 @@ -from django.forms import Field +from django.forms import ChoiceField, Field, Form, Select from django.test import SimpleTestCase @@ -20,3 +20,17 @@ class BasicFieldsTests(SimpleTestCase): f = ComplexField() self.assertTrue(f.class_a_var) + + def test_field_deepcopies_widget_instance(self): + class CustomChoiceField(ChoiceField): + widget = Select(attrs={'class': 'my-custom-class'}) + + class TestForm(Form): + field1 = CustomChoiceField(choices=[]) + field2 = CustomChoiceField(choices=[]) + + f = TestForm() + f.fields['field1'].choices = [('1', '1')] + f.fields['field2'].choices = [('2', '2')] + self.assertEqual(f.fields['field1'].widget.choices, [('1', '1')]) + self.assertEqual(f.fields['field2'].widget.choices, [('2', '2')]) diff --git a/tests/model_forms/tests.py b/tests/model_forms/tests.py index 53e70c6ae9..289d8604b3 100644 --- a/tests/model_forms/tests.py +++ b/tests/model_forms/tests.py @@ -2867,7 +2867,7 @@ class FormFieldCallbackTests(SimpleTestCase): fields = "__all__" Form = modelform_factory(Person, form=BaseForm) - self.assertIs(Form.base_fields['name'].widget, widget) + self.assertIsInstance(Form.base_fields['name'].widget, forms.Textarea) def test_factory_with_widget_argument(self): """ Regression for #15315: modelform_factory should accept widgets