Opened 16 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 )
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.
- Create a ModelForm
- Add it to ModelAdmin
- View Form
- Update ModelForm's
__init__to includeself.fields['xyz'] = forms.CharField(max_length=255, initial='keke') - View Form (note no change)
- Update ModelForm's
Meta.fieldsto include "xyz" - View Form (note the change)
Attachments (1)
Change History (12)
comment:1 by , 16 years ago
| Component: | Uncategorized → django.contrib.admin |
|---|
comment:2 by , 16 years ago
| Has patch: | set |
|---|
comment:3 by , 16 years ago
| Description: | modified (diff) |
|---|---|
| Has patch: | unset |
(reformat description, also it hasn't a patch until it has a patch)
comment:4 by , 16 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 , 16 years ago
| Attachment: | dynamic-fieldsets-0.1.diff added |
|---|
Attempt to use dynamic fieldsets generation
comment:5 by , 16 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 , 16 years ago
| Needs tests: | set |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
comment:7 by , 15 years ago
| Severity: | → Normal |
|---|---|
| Type: | → Bug |
comment:8 by , 15 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:11 by , 4 years ago
- Update ModelForm's
Meta.fieldsto 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.
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?