Author: jezdez
Date: 2011-08-12 07:14:49 -0700 (Fri, 12 Aug 2011)
New Revision: 16602
Modified:
django/trunk/django/contrib/admin/options.py
django/trunk/docs/ref/contrib/admin/index.txt
django/trunk/tests/regressiontests/modeladmin/tests.py
Log:
Fixed #14496 -- Fixed conflict between ModelForm exclude and ModelAdmin
readonly values. Thanks, Julien Phalip.
Modified: django/trunk/django/contrib/admin/options.py
===================================================================
--- django/trunk/django/contrib/admin/options.py 2011-08-12 14:14:39 UTC
(rev 16601)
+++ django/trunk/django/contrib/admin/options.py 2011-08-12 14:14:49 UTC
(rev 16602)
@@ -437,6 +437,10 @@
else:
exclude = list(self.exclude)
exclude.extend(self.get_readonly_fields(request, obj))
+ if self.exclude is None and hasattr(self.form, '_meta') and
self.form._meta.exclude:
+ # Take the custom ModelForm's Meta.exclude into account only if the
+ # ModelAdmin doesn't define its own.
+ exclude.extend(self.form._meta.exclude)
# if exclude is an empty list we pass None to be consistant with the
# default on modelform_factory
exclude = exclude or None
@@ -1343,6 +1347,10 @@
else:
exclude = list(self.exclude)
exclude.extend(self.get_readonly_fields(request, obj))
+ if self.exclude is None and hasattr(self.form, '_meta') and
self.form._meta.exclude:
+ # Take the custom ModelForm's Meta.exclude into account only if the
+ # InlineModelAdmin doesn't define its own.
+ exclude.extend(self.form._meta.exclude)
# if exclude is an empty list we use None, since that's the actual
# default
exclude = exclude or None
Modified: django/trunk/docs/ref/contrib/admin/index.txt
===================================================================
--- django/trunk/docs/ref/contrib/admin/index.txt 2011-08-12 14:14:39 UTC
(rev 16601)
+++ django/trunk/docs/ref/contrib/admin/index.txt 2011-08-12 14:14:49 UTC
(rev 16602)
@@ -313,6 +313,24 @@
For an example see the section `Adding custom validation to the admin`_.
+ .. admonition:: Note
+
+ If your ``ModelForm`` and ``ModelAdmin`` both define an ``exclude``
+ option then ``ModelAdmin`` takes precedence::
+
+ class PersonForm(forms.ModelForm):
+
+ class Meta:
+ model = Person
+ exclude = ['name']
+
+ class PersonAdmin(admin.ModelAdmin):
+ exclude = ['age']
+ form = PersonForm
+
+ In the above example, the "age" field will be excluded but the "name"
+ field will be included in the generated form.
+
.. attribute:: ModelAdmin.formfield_overrides
This provides a quick-and-dirty way to override some of the
Modified: django/trunk/tests/regressiontests/modeladmin/tests.py
===================================================================
--- django/trunk/tests/regressiontests/modeladmin/tests.py 2011-08-12
14:14:39 UTC (rev 16601)
+++ django/trunk/tests/regressiontests/modeladmin/tests.py 2011-08-12
14:14:49 UTC (rev 16602)
@@ -120,6 +120,99 @@
self.assertEqual(ma.get_form(request).base_fields.keys(),
['name'])
+ def test_custom_form_meta_exclude_with_readonly(self):
+ """
+ Ensure that the custom ModelForm's `Meta.exclude` is respected when
+ used in conjunction with `ModelAdmin.readonly_fields` and when no
+ `ModelAdmin.exclude` is defined.
+ Refs #14496.
+ """
+ # First, with `ModelAdmin` -----------------------
+
+ class AdminBandForm(forms.ModelForm):
+
+ class Meta:
+ model = Band
+ exclude = ['bio']
+
+ class BandAdmin(ModelAdmin):
+ readonly_fields = ['name']
+ form = AdminBandForm
+
+ ma = BandAdmin(Band, self.site)
+ self.assertEqual(ma.get_form(request).base_fields.keys(),
+ ['sign_date',])
+
+ # Then, with `InlineModelAdmin` -----------------
+
+ class AdminConcertForm(forms.ModelForm):
+
+ class Meta:
+ model = Concert
+ exclude = ['day']
+
+ class ConcertInline(TabularInline):
+ readonly_fields = ['transport']
+ form = AdminConcertForm
+ fk_name = 'main_band'
+ model = Concert
+
+ class BandAdmin(ModelAdmin):
+ inlines = [
+ ConcertInline
+ ]
+
+ ma = BandAdmin(Band, self.site)
+ self.assertEqual(
+ list(ma.get_formsets(request))[0]().forms[0].fields.keys(),
+ ['main_band', 'opening_band', 'id', 'DELETE',])
+
+ def test_custom_form_meta_exclude(self):
+ """
+ Ensure that the custom ModelForm's `Meta.exclude` is overridden if
+ `ModelAdmin.exclude` or `InlineModelAdmin.exclude` are defined.
+ Refs #14496.
+ """
+ # First, with `ModelAdmin` -----------------------
+
+ class AdminBandForm(forms.ModelForm):
+
+ class Meta:
+ model = Band
+ exclude = ['bio']
+
+ class BandAdmin(ModelAdmin):
+ exclude = ['name']
+ form = AdminBandForm
+
+ ma = BandAdmin(Band, self.site)
+ self.assertEqual(ma.get_form(request).base_fields.keys(),
+ ['bio', 'sign_date',])
+
+ # Then, with `InlineModelAdmin` -----------------
+
+ class AdminConcertForm(forms.ModelForm):
+
+ class Meta:
+ model = Concert
+ exclude = ['day']
+
+ class ConcertInline(TabularInline):
+ exclude = ['transport']
+ form = AdminConcertForm
+ fk_name = 'main_band'
+ model = Concert
+
+ class BandAdmin(ModelAdmin):
+ inlines = [
+ ConcertInline
+ ]
+
+ ma = BandAdmin(Band, self.site)
+ self.assertEqual(
+ list(ma.get_formsets(request))[0]().forms[0].fields.keys(),
+ ['main_band', 'opening_band', 'day', 'id', 'DELETE',])
+
def test_custom_form_validation(self):
# If we specify a form, it should use it allowing custom validation to
work
# properly. This won't, however, break any of the admin widgets or
media.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en.