Opened 3 months ago

Closed 3 months ago

#35696 closed Bug (invalid)

ModelAdmin is overruling the fields of ModelForm

Reported by: Jurrian Tromp Owned by:
Component: Forms Version: 4.2
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Jurrian Tromp)

It seems that in ModelForm both field_order and Meta.fields ordering is being overruled by the admin change view. When rendering, the form object initially has the correct order, but when admin_form (django.contrib.admin.options:1826) is created, the fieldsets (django.contrib.admin.options:1781) coming from get_fieldsets() overrides the correct order in form.fields.

Something similar in #19514 has been reported before, more or less saying that ModelAdmin order should be leading. The problem with this however is that the reason you have a ModelForm here this way is because you try to do something more specialized. Consider this:

class Message(models.Model):
    some_readonly = models.CharField(...)
    overruled_model_m2m_field = models.ManyToManyField(through=SomeModel, ...)

class MessageForm(forms.ModelForm):
    some_form_field = forms.CharField()
    overruled_model_m2m_field = forms.CharField()

    field_order = ['some_form_field', 'overruled_model_m2m_field']

    class Meta:
        model = Message
        fields = ['some_form_field', 'overruled_model_m2m_field']
        exclude = ['some_readonly']

class MessageAdmin(admin.ModelAdmin):
    readonly_fields = ['some_readonly']
    form = MessageForm

Resulting in the following unexpected behavior:

  1. For the fields MessageForm is ignored for the most part, MessageAdmin.get_fields() is de-facto shown.
    1. ModelAdmin readonly_fields are shown, even when they are excluded in the ModelForm.
    2. MessageForm.field_order has no effect when used in an admin view.
  2. When a model field has through, it is not shown, as it should be an inline. Although it will be added to the fields again in the form (MessageForm.overruled_model_m2m_field)
    1. This makes it appear "randomly" in the ordering as it is updated to the end of base_fields (django.forms.models:324)

Expected behavior:

  1. MessageForm takes precedence over MessageAdmin.
    1. Excluded fields are not shown
    2. ModelForm.Meta.fields and ModelForm.field_order are used in favor of ModelAdmin.get_fields()
  2. a. Fields with a through that are also specified in the form itself are ordered correctly according to 1b.

There are workarounds to get both the field order and readonly fields right, which comes down to defining MessageAdmin.get_fields() and/or MessageAdmin.get_readonly_fields(), to take full control. However, IMHO this should not be the default.

Change History (2)

comment:1 by Jurrian Tromp, 3 months ago

Description: modified (diff)

comment:2 by Carlton Gibson, 3 months ago

Resolution: invalid
Status: newclosed

This is the expected behaviour as far as I can see. The ModelAdmin.form docs state that the fields meta option is ignored on any provided form. (The provided form class is used as the base, but fields are derived from the admin options fields/fieldsets.)

If you want to bypass the form generation you should override get_form().

I'd suggest following up in TicketClosingReasons/UseSupportChannels if you need to dig further.

Note: See TracTickets for help on using tickets.
Back to Top