Ticket #14496: 14496.custom-admin-form-exclude.alternative.diff
File 14496.custom-admin-form-exclude.alternative.diff, 6.0 KB (added by , 13 years ago) |
---|
-
django/contrib/admin/options.py
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index c603210..73e1e30 100644
a b class ModelAdmin(BaseModelAdmin): 428 428 exclude = list(self.exclude) 429 429 exclude.extend(kwargs.get("exclude", [])) 430 430 exclude.extend(self.get_readonly_fields(request, obj)) 431 if self.exclude is None and hasattr(self.form, '_meta') and self.form._meta.exclude: 432 # Take the custom ModelForm's Meta.exclude into account only if the 433 # ModelAdmin doesn't define its own. 434 exclude.extend(self.form.Meta.exclude) 431 435 # if exclude is an empty list we pass None to be consistant with the 432 436 # default on modelform_factory 433 437 exclude = exclude or None … … class InlineModelAdmin(BaseModelAdmin): 1330 1334 exclude = list(self.exclude) 1331 1335 exclude.extend(kwargs.get("exclude", [])) 1332 1336 exclude.extend(self.get_readonly_fields(request, obj)) 1337 if self.exclude is None and hasattr(self.form, '_meta') and self.form._meta.exclude: 1338 # Take the custom ModelForm's Meta.exclude into account only if the 1339 # InlineModelAdmin doesn't define its own. 1340 exclude.extend(self.form.Meta.exclude) 1333 1341 # if exclude is an empty list we use None, since that's the actual 1334 1342 # default 1335 1343 exclude = exclude or None -
docs/ref/contrib/admin/index.txt
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt index fb48ba8..ba890ec 100644
a b subclass:: 293 293 294 294 For an example see the section `Adding custom validation to the admin`_. 295 295 296 .. admonition:: Note 297 298 If your ``ModelForm`` and ``ModelAdmin`` both define an ``exclude`` 299 option then ``ModelAdmin`` takes precedence:: 300 301 class PersonForm(forms.ModelForm): 302 303 class Meta: 304 model = Person 305 exclude = ['name'] 306 307 class PersonAdmin(admin.ModelAdmin): 308 exclude = ['age'] 309 form = PersonForm 310 311 In the above example, the "age" field will be excluded but the "name" 312 field will be included in the generated form. 313 296 314 .. attribute:: ModelAdmin.formfield_overrides 297 315 298 316 This provides a quick-and-dirty way to override some of the -
tests/regressiontests/modeladmin/tests.py
diff --git a/tests/regressiontests/modeladmin/tests.py b/tests/regressiontests/modeladmin/tests.py index 530b476..af0ae33 100644
a b class ModelAdminTests(TestCase): 119 119 ma = BandAdmin(Band, self.site) 120 120 self.assertEqual(ma.get_form(request).base_fields.keys(), 121 121 ['name']) 122 123 def test_custom_form_meta_exclude_with_readonly(self): 124 """ 125 Ensure that the custom ModelForm's `Meta.exclude` is respected when 126 used in conjunction with `ModelAdmin.readonly_fields` and when no 127 `ModelAdmin.exclude` is defined. 128 Refs #14496. 129 """ 130 # First, with `ModelAdmin` ----------------------- 131 132 class AdminBandForm(forms.ModelForm): 133 134 class Meta: 135 model = Band 136 exclude = ['bio'] 122 137 138 class BandAdmin(ModelAdmin): 139 readonly_fields = ['name'] 140 form = AdminBandForm 141 142 ma = BandAdmin(Band, self.site) 143 self.assertEqual(ma.get_form(request).base_fields.keys(), 144 ['sign_date',]) 145 146 # Then, with `InlineModelAdmin` ----------------- 147 148 class AdminConcertForm(forms.ModelForm): 149 150 class Meta: 151 model = Concert 152 exclude = ['day'] 153 154 class ConcertInline(TabularInline): 155 readonly_fields = ['transport'] 156 form = AdminConcertForm 157 fk_name = 'main_band' 158 model = Concert 159 160 class BandAdmin(ModelAdmin): 161 inlines = [ 162 ConcertInline 163 ] 164 165 ma = BandAdmin(Band, self.site) 166 self.assertEqual( 167 list(ma.get_formsets(request))[0]().forms[0].fields.keys(), 168 ['main_band', 'opening_band', 'id', 'DELETE',]) 169 170 def test_custom_form_meta_exclude(self): 171 """ 172 Ensure that the custom ModelForm's `Meta.exclude` is overridden if 173 `ModelAdmin.exclude` or `InlineModelAdmin.exclude` are defined. 174 Refs #14496. 175 """ 176 # First, with `ModelAdmin` ----------------------- 177 178 class AdminBandForm(forms.ModelForm): 179 180 class Meta: 181 model = Band 182 exclude = ['bio'] 183 184 class BandAdmin(ModelAdmin): 185 exclude = ['name'] 186 form = AdminBandForm 187 188 ma = BandAdmin(Band, self.site) 189 self.assertEqual(ma.get_form(request).base_fields.keys(), 190 ['bio', 'sign_date',]) 191 192 # Then, with `InlineModelAdmin` ----------------- 193 194 class AdminConcertForm(forms.ModelForm): 195 196 class Meta: 197 model = Concert 198 exclude = ['day'] 199 200 class ConcertInline(TabularInline): 201 exclude = ['transport'] 202 form = AdminConcertForm 203 fk_name = 'main_band' 204 model = Concert 205 206 class BandAdmin(ModelAdmin): 207 inlines = [ 208 ConcertInline 209 ] 210 211 ma = BandAdmin(Band, self.site) 212 self.assertEqual( 213 list(ma.get_formsets(request))[0]().forms[0].fields.keys(), 214 ['main_band', 'opening_band', 'day', 'id', 'DELETE',]) 215 123 216 def test_custom_form_validation(self): 124 217 # If we specify a form, it should use it allowing custom validation to work 125 218 # properly. This won't, however, break any of the admin widgets or media.