summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2012-12-08 12:41:11 +0100
committerClaude Paroz <claude@2xlibre.net>2012-12-08 12:47:33 +0100
commitfa5460460696863ebd7c8ebae325b4ebce1a777b (patch)
tree6d8aceafaf0f04a740bcafab704b69701b38acf4
parent9af9cdb3eb21617bae37c159d8ab94a4688e3b3f (diff)
[1.5.x] Fixed #19423 -- Prevented ModelAdmin sharing widgets due to formfield_overrides
Thanks joebuyer at manycycles.com for the report and Simon Charette for the review. Backport of 04e6542b5 from master.
-rw-r--r--django/contrib/admin/options.py3
-rw-r--r--tests/regressiontests/admin_widgets/models.py1
-rw-r--r--tests/regressiontests/admin_widgets/tests.py19
3 files changed, 21 insertions, 2 deletions
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index c48ffa6ca3..f4c27511d3 100644
--- a/django/contrib/admin/options.py
+++ b/django/contrib/admin/options.py
@@ -1,3 +1,4 @@
+import copy
from functools import update_wrapper, partial
import warnings
@@ -130,7 +131,7 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
# passed to formfield_for_dbfield override the defaults.
for klass in db_field.__class__.mro():
if klass in self.formfield_overrides:
- kwargs = dict(self.formfield_overrides[klass], **kwargs)
+ kwargs = dict(copy.deepcopy(self.formfield_overrides[klass]), **kwargs)
return db_field.formfield(**kwargs)
# For any other type of field, just call its formfield() method.
diff --git a/tests/regressiontests/admin_widgets/models.py b/tests/regressiontests/admin_widgets/models.py
index 2e452798b7..2977b86f3e 100644
--- a/tests/regressiontests/admin_widgets/models.py
+++ b/tests/regressiontests/admin_widgets/models.py
@@ -20,6 +20,7 @@ class Member(models.Model):
@python_2_unicode_compatible
class Band(models.Model):
name = models.CharField(max_length=100)
+ style = models.CharField(max_length=20)
members = models.ManyToManyField(Member)
def __str__(self):
diff --git a/tests/regressiontests/admin_widgets/tests.py b/tests/regressiontests/admin_widgets/tests.py
index 0b016d885b..76aa9f448f 100644
--- a/tests/regressiontests/admin_widgets/tests.py
+++ b/tests/regressiontests/admin_widgets/tests.py
@@ -10,7 +10,7 @@ from django.contrib.admin import widgets
from django.contrib.admin.tests import AdminSeleniumWebDriverTestCase
from django.core.files.storage import default_storage
from django.core.files.uploadedfile import SimpleUploadedFile
-from django.db.models import DateField
+from django.db.models import CharField, DateField
from django.test import TestCase as DjangoTestCase
from django.test.utils import override_settings
from django.utils import translation
@@ -112,6 +112,23 @@ class AdminFormfieldForDBFieldTests(TestCase):
self.assertFormfield(models.Event, 'start_date', forms.TextInput,
formfield_overrides={DateField: {'widget': forms.TextInput}})
+ def testFormfieldOverridesWidgetInstances(self):
+ """
+ Test that widget instances in formfield_overrides are not shared between
+ different fields. (#19423)
+ """
+ class BandAdmin(admin.ModelAdmin):
+ formfield_overrides = {
+ CharField: {'widget': forms.TextInput(attrs={'size':'10'})}
+ }
+ ma = BandAdmin(models.Band, admin.site)
+ f1 = ma.formfield_for_dbfield(models.Band._meta.get_field('name'), request=None)
+ f2 = ma.formfield_for_dbfield(models.Band._meta.get_field('style'), request=None)
+ self.assertNotEqual(f1.widget, f2.widget)
+ self.assertEqual(f1.widget.attrs['maxlength'], '100')
+ self.assertEqual(f2.widget.attrs['maxlength'], '20')
+ self.assertEqual(f2.widget.attrs['size'], '10')
+
def testFieldWithChoices(self):
self.assertFormfield(models.Member, 'gender', forms.Select)