mirror of
				https://github.com/django/django.git
				synced 2025-10-28 08:06:09 +00:00 
			
		
		
		
	[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.
			
			
This commit is contained in:
		| @@ -1,3 +1,4 @@ | |||||||
|  | import copy | ||||||
| from functools import update_wrapper, partial | from functools import update_wrapper, partial | ||||||
| import warnings | import warnings | ||||||
|  |  | ||||||
| @@ -130,7 +131,7 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)): | |||||||
|         # passed to formfield_for_dbfield override the defaults. |         # passed to formfield_for_dbfield override the defaults. | ||||||
|         for klass in db_field.__class__.mro(): |         for klass in db_field.__class__.mro(): | ||||||
|             if klass in self.formfield_overrides: |             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) |                 return db_field.formfield(**kwargs) | ||||||
|  |  | ||||||
|         # For any other type of field, just call its formfield() method. |         # For any other type of field, just call its formfield() method. | ||||||
|   | |||||||
| @@ -20,6 +20,7 @@ class Member(models.Model): | |||||||
| @python_2_unicode_compatible | @python_2_unicode_compatible | ||||||
| class Band(models.Model): | class Band(models.Model): | ||||||
|     name = models.CharField(max_length=100) |     name = models.CharField(max_length=100) | ||||||
|  |     style = models.CharField(max_length=20) | ||||||
|     members = models.ManyToManyField(Member) |     members = models.ManyToManyField(Member) | ||||||
|  |  | ||||||
|     def __str__(self): |     def __str__(self): | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ from django.contrib.admin import widgets | |||||||
| from django.contrib.admin.tests import AdminSeleniumWebDriverTestCase | from django.contrib.admin.tests import AdminSeleniumWebDriverTestCase | ||||||
| from django.core.files.storage import default_storage | from django.core.files.storage import default_storage | ||||||
| from django.core.files.uploadedfile import SimpleUploadedFile | 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 import TestCase as DjangoTestCase | ||||||
| from django.test.utils import override_settings | from django.test.utils import override_settings | ||||||
| from django.utils import translation | from django.utils import translation | ||||||
| @@ -112,6 +112,23 @@ class AdminFormfieldForDBFieldTests(TestCase): | |||||||
|         self.assertFormfield(models.Event, 'start_date', forms.TextInput, |         self.assertFormfield(models.Event, 'start_date', forms.TextInput, | ||||||
|                              formfield_overrides={DateField: {'widget': 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): |     def testFieldWithChoices(self): | ||||||
|         self.assertFormfield(models.Member, 'gender', forms.Select) |         self.assertFormfield(models.Member, 'gender', forms.Select) | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user