Commit fedef7b2 authored by jpic's avatar jpic Committed by Tim Graham
Browse files

Fixed #24908 -- Fixed duplicate readonly field rendering.

ModelAdmin added readonly_fields to exclude, but would not undeclare
them if they were overridden.
parent 60f795c0
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -605,7 +605,8 @@ class ModelAdmin(BaseModelAdmin):
            exclude = []
        else:
            exclude = list(self.exclude)
        exclude.extend(self.get_readonly_fields(request, obj))
        readonly_fields = self.get_readonly_fields(request, obj)
        exclude.extend(readonly_fields)
        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.
@@ -613,8 +614,16 @@ class ModelAdmin(BaseModelAdmin):
        # if exclude is an empty list we pass None to be consistent with the
        # default on modelform_factory
        exclude = exclude or None

        # Remove declared form fields which are in readonly_fields.
        new_attrs = OrderedDict(
            (f, None) for f in readonly_fields
            if f in self.form.declared_fields
        )
        form = type(self.form.__name__, (self.form,), new_attrs)

        defaults = {
            "form": self.form,
            "form": form,
            "fields": fields,
            "exclude": exclude,
            "formfield_callback": partial(self.formfield_for_dbfield, request=request),
+31 −0
Original line number Diff line number Diff line
@@ -221,6 +221,37 @@ class ModelAdminTests(TestCase):
            list(list(ma.get_formsets_with_inlines(request))[0][0]().forms[0].fields),
            ['main_band', 'opening_band', 'id', 'DELETE'])

    def test_custom_formfield_override_readonly(self):
        class AdminBandForm(forms.ModelForm):
            name = forms.CharField()

            class Meta:
                exclude = tuple()
                model = Band

        class BandAdmin(ModelAdmin):
            form = AdminBandForm
            readonly_fields = ['name']

        ma = BandAdmin(Band, self.site)

        # `name` shouldn't appear in base_fields because it's part of
        # readonly_fields.
        self.assertEqual(
            list(ma.get_form(request).base_fields),
            ['bio', 'sign_date']
        )
        # But it should appear in get_fields()/fieldsets() so it can be
        # displayed as read-only.
        self.assertEqual(
            list(ma.get_fields(request)),
            ['bio', 'sign_date', 'name']
        )
        self.assertEqual(
            list(ma.get_fieldsets(request)),
            [(None, {'fields': ['bio', 'sign_date', 'name']})]
        )

    def test_custom_form_meta_exclude(self):
        """
        Ensure that the custom ModelForm's `Meta.exclude` is overridden if