Code

Ticket #19423: 19423-1.diff

File 19423-1.diff, 3.2 KB (added by claudep, 17 months ago)
Line 
1diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
2index c48ffa6..f4c2751 100644
3--- a/django/contrib/admin/options.py
4+++ b/django/contrib/admin/options.py
5@@ -1,3 +1,4 @@
6+import copy
7 from functools import update_wrapper, partial
8 import warnings
9 
10@@ -130,7 +131,7 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
11         # passed to formfield_for_dbfield override the defaults.
12         for klass in db_field.__class__.mro():
13             if klass in self.formfield_overrides:
14-                kwargs = dict(self.formfield_overrides[klass], **kwargs)
15+                kwargs = dict(copy.deepcopy(self.formfield_overrides[klass]), **kwargs)
16                 return db_field.formfield(**kwargs)
17 
18         # For any other type of field, just call its formfield() method.
19diff --git a/tests/regressiontests/admin_widgets/models.py b/tests/regressiontests/admin_widgets/models.py
20index 2e45279..2977b86 100644
21--- a/tests/regressiontests/admin_widgets/models.py
22+++ b/tests/regressiontests/admin_widgets/models.py
23@@ -20,6 +20,7 @@ class Member(models.Model):
24 @python_2_unicode_compatible
25 class Band(models.Model):
26     name = models.CharField(max_length=100)
27+    style = models.CharField(max_length=20)
28     members = models.ManyToManyField(Member)
29 
30     def __str__(self):
31diff --git a/tests/regressiontests/admin_widgets/tests.py b/tests/regressiontests/admin_widgets/tests.py
32index 0b016d8..76aa9f4 100644
33--- a/tests/regressiontests/admin_widgets/tests.py
34+++ b/tests/regressiontests/admin_widgets/tests.py
35@@ -10,7 +10,7 @@ from django.contrib.admin import widgets
36 from django.contrib.admin.tests import AdminSeleniumWebDriverTestCase
37 from django.core.files.storage import default_storage
38 from django.core.files.uploadedfile import SimpleUploadedFile
39-from django.db.models import DateField
40+from django.db.models import CharField, DateField
41 from django.test import TestCase as DjangoTestCase
42 from django.test.utils import override_settings
43 from django.utils import translation
44@@ -112,6 +112,23 @@ class AdminFormfieldForDBFieldTests(TestCase):
45         self.assertFormfield(models.Event, 'start_date', forms.TextInput,
46                              formfield_overrides={DateField: {'widget': forms.TextInput}})
47 
48+    def testFormfieldOverridesWidgetInstances(self):
49+        """
50+        Test that widget instances in formfield_overrides are not shared between
51+        different fields. (#19423)
52+        """
53+        class BandAdmin(admin.ModelAdmin):
54+            formfield_overrides = {
55+                CharField: {'widget': forms.TextInput(attrs={'size':'10'})}
56+            }
57+        ma = BandAdmin(models.Band, admin.site)
58+        f1 = ma.formfield_for_dbfield(models.Band._meta.get_field('name'), request=None)
59+        f2 = ma.formfield_for_dbfield(models.Band._meta.get_field('style'), request=None)
60+        self.assertNotEqual(f1.widget, f2.widget)
61+        self.assertEqual(f1.widget.attrs['maxlength'], '100')
62+        self.assertEqual(f2.widget.attrs['maxlength'], '20')
63+        self.assertEqual(f2.widget.attrs['size'], '10')
64+
65     def testFieldWithChoices(self):
66         self.assertFormfield(models.Member, 'gender', forms.Select)
67