Skip to content

Commit

Permalink
Fixed #19423 -- Prevented ModelAdmin sharing widgets due to formfield…
Browse files Browse the repository at this point in the history
…_overrides

Thanks joebuyer at manycycles.com for the report and Simon Charette
for the review.
  • Loading branch information
claudep committed Dec 8, 2012
1 parent 6140795 commit 04e6542
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 2 deletions.
3 changes: 2 additions & 1 deletion django/contrib/admin/options.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import copy
from functools import update_wrapper, partial
import warnings

Expand Down Expand Up @@ -130,7 +131,7 @@ def formfield_for_dbfield(self, db_field, **kwargs):
# 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.
Expand Down
1 change: 1 addition & 0 deletions tests/regressiontests/admin_widgets/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def __str__(self):
@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):
Expand Down
19 changes: 18 additions & 1 deletion tests/regressiontests/admin_widgets/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
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
Expand Down Expand Up @@ -112,6 +112,23 @@ def testFormfieldOverrides(self):
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)

Expand Down

0 comments on commit 04e6542

Please sign in to comment.