Opened 14 years ago

Last modified 2 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 Morales)

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 Bieler 14 years ago.
Attempt to use dynamic fieldsets generation

Download all attachments as: .zip

Change History (12)

comment:1 by anonymous, 14 years ago

Component: Uncategorizeddjango.contrib.admin

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 by anonymous, 14 years ago

Has patch: set

comment:3 by Ramiro Morales, 14 years ago

Description: modified (diff)
Has patch: unset

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

comment:4 by Batiste Bieler, 14 years ago

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

I can provide a patch if needed.

by Batiste Bieler, 14 years ago

Attachment: dynamic-fieldsets-0.1.diff added

Attempt to use dynamic fieldsets generation

comment:5 by Batiste Bieler, 14 years ago

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 by Russell Keith-Magee, 14 years ago

Needs tests: set
Triage Stage: UnreviewedAccepted

comment:7 by Matt McClanahan, 13 years ago

Severity: Normal
Type: Bug

comment:8 by anonymous, 13 years ago

@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 by Aymeric Augustin, 12 years ago

UI/UX: unset

Change UI/UX from NULL to False.

comment:10 by Aymeric Augustin, 12 years ago

Easy pickings: unset

Change Easy pickings from NULL to False.

comment:11 by François Freitag, 2 years ago

  1. Update ModelForm's Meta.fields to include "xyz"

This step leaves the Meta.fields modified, because the Meta is only instantiated when the ModelForm class is constructed. Thus, on the next request, "xyz" will still be part of the Meta.fields. In my use case, the field was added conditionally, and was unexpectedly present in the Meta.fields on the next request.

This might be a pitfall for others.

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