Opened 6 years ago

Last modified 4 years ago

#12238 new Bug

ModelAdmin ignores dynamic fields of ModelForm

Reported by: anonymous Owned by: nobody
Component: contrib.admin Version: 1.1
Severity: Normal Keywords: modelform modeladmin dynamic field
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: yes Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by ramiro)

If a ModelForm is created and then modified to programatically add fields (say, in __init__), ModelAdmin ignores these fields when rendering the form. If one of these fields is added to the ModelForm's Meta, the field shows up just fine.

I would expect the field to display without the coaxing in Meta.fields.

  1. Create a ModelForm
  2. Add it to ModelAdmin
  3. View Form
  4. Update ModelForm's __init__ to include self.fields['xyz'] = forms.CharField(max_length=255, initial='keke')
  5. View Form (note no change)
  6. Update ModelForm's Meta.fields to include "xyz"
  7. View Form (note the change)

Attachments (1)

dynamic-fieldsets-0.1.diff (1.9 KB) - added by batiste 6 years ago.
Attempt to use dynamic fieldsets generation

Download all attachments as: .zip

Change History (11)

comment:1 Changed 6 years ago by anonymous

  • Component changed from Uncategorized to django.contrib.admin
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

I've solved this in the meantime by updating contrib/admin/options.py in:

    def get_fieldsets(self, request, obj=None):
        "Hook for specifying fieldsets for the add form."
        if self.declared_fieldsets:
            return self.declared_fieldsets
        #form = self.get_form(request, obj)
        #return [(None, {'fields': form.base_fields.keys()})]
        form = self.get_form(request, obj)(instance=obj)
        return [(None, {'fields': form.fields.keys()})]

Seems to be a harmless fix, possible to get this applied upstream?

comment:2 Changed 6 years ago by anonymous

  • Has patch set

comment:3 Changed 6 years ago by ramiro

  • Description modified (diff)
  • Has patch unset

(reformat description, also it hasn't a patch until it has a patch)

comment:4 Changed 6 years ago by batiste

I think the declared_fieldsets too satic too. Why not using a callable that people can override?

I can provide a patch if needed.

Changed 6 years ago by batiste

Attempt to use dynamic fieldsets generation

comment:5 Changed 6 years ago by batiste

  • Has patch set

The patch I sent seems to work quite oki, but if I add a field dynamicaly, even if it's in the form object, the new value is not saved:

    def dynamic_fieldsets(self, request, obj=None, **kwargs):

        general_fields = list(self.general_fields)
        perms = PagePermission(request.user)

        if perms.check('freeze'):
            general_fields.append('freeze_date')

        return [
            [_('General'), {
                'fields': general_fields,
                'classes': ('module-general',),
            }],
            (_('Options'), {
                'fields': self.normal_fields,
                'classes': ('module-options',),
            }),
        ]

My freeze field is added properly in the admin interface, but the value is not saved. But in the other hand if I do things like that:

    def get_fieldsets(self, request, obj=None):
        """
        Add fieldsets of placeholders to the list of already
        existing fieldsets.
        """
        general_fields = list(self.general_fields)
        perms = PagePermission(request.user)

        # some ugly business to remove freeze_date
        # from the field list
        general_module = {
            'fields': list(self.general_fields),
            'classes': ('module-general',),
        }

        default_fieldsets = list(self.fieldsets)
        if not perms.check('freeze'):
            general_module['fields'].remove('freeze_date')

        default_fieldsets[0][1] = general_module

The latest version works, but it feels like a very hackish way to do things.

Can somebody explain me what's wrong here? Does Django have a more elegant way to do this?

comment:6 Changed 6 years ago by russellm

  • Needs tests set
  • Triage Stage changed from Unreviewed to Accepted

comment:7 Changed 4 years ago by mattmcc

  • Severity set to Normal
  • Type set to Bug

comment:8 Changed 4 years ago by anonymous

@anonymous 6.Update ModelForm's Meta.fields to include "xyz" - howto? my Meta has no attr 'fields' while runtime in init
I have the same problem - trying to add dynamic field to ModelForm

comment:9 Changed 4 years ago by aaugustin

  • UI/UX unset

Change UI/UX from NULL to False.

comment:10 Changed 4 years ago by aaugustin

  • Easy pickings unset

Change Easy pickings from NULL to False.

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