Opened 16 years ago
Closed 11 years ago
#8387 closed Bug (fixed)
Returning a subset of the models fields in ModelAdmin.get_fieldsets only works when also overriding get_form
Reported by: | Owned by: | nobody | |
---|---|---|---|
Component: | Documentation | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
If you return only a subset of your models fields in get_fieldsets
you need to override
get_form
as well and set the
fields
or
exclude
attribute. Otherwise the form will expect *all* fields to be present and will either raise validation errors on the missing fields or clear them if they have
blank=True
.
This won't work:
class MyModelAdmin(admin.ModelAdmin): def get_fieldsets(self, request, obj=None): if obj: return [(None, {'fields': ('field_c', 'field_b')})] return [(None, {'fields': ('field_a', 'field_b', 'field_c')})]
But this will:
class MyModelAdmin(admin.ModelAdmin): def get_fieldsets(self, request, obj=None): if obj: return [(None, {'fields': ('field_c', 'field_b')})] return [(None, {'fields': ('field_a', 'field_b', 'field_c')})] def get_form(self, request, obj=None, **kwargs): if obj: defaults = {'exclude': ('field_a',)} else: defaults = {} defaults.update(kwargs) return super(MyModelAdmin, self).get_form(request, obj, **defaults)
The reason for this is that Django cannot provide a sensible default for both cases:
- Just override
get_form
- Just override
get_fieldsets
In the first case get_fieldsets
calls the overriden
get_form
and can so determine a default value for fieldsets. But this means that the default implementation of
get_form
cannot call
get_fieldsets
as this would create an infinite loop.
Which function calls the other could be discussed -- maybe overriding get_fieldsets
is much more common? But in the case it stays like it is the attached patch documents the behavior.
Attachments (4)
Change History (14)
by , 16 years ago
Attachment: | get_form+get_fieldsets-docs-00.diff added |
---|
comment:1 by , 16 years ago
I don't know if we want to recommend flatten_fieldsets() for public use. But if we would this is the much cleaner method to use if you need to override get_form() just to work around the get_fieldsets() gotcha:
from django.contrib.admin.util import flatten_fieldsets def get_form(self, request, obj=None, **kwargs): defaults = { 'fields': flatten_fieldsets(self.get_fieldsets(request, obj)), } defaults.update(kwargs) return super(FrontpageImageOptions, self).get_form(request, obj, **defaults)
by , 16 years ago
Attachment: | get_form+get_fieldsets-docs-01.diff added |
---|
Updated the patch for the docs refactor
by , 16 years ago
Attachment: | get_form+get_fieldsets-docs-02.2.diff added |
---|
by , 16 years ago
Attachment: | get_form+get_fieldsets-docs-02.diff added |
---|
Alternate version using flatten_fieldsets()
comment:2 by , 16 years ago
milestone: | 1.0 → post-1.0 |
---|
comment:4 by , 16 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:5 by , 14 years ago
Another annoying inconsistency is that a form returned with get_form will not be respected by fieldsets argument on the ModelAdmin.
comment:6 by , 14 years ago
Severity: | → Normal |
---|---|
Type: | → Bug |
comment:9 by , 11 years ago
Component: | contrib.admin → Documentation |
---|---|
Has patch: | set |
comment:10 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
"If you return only a subset of your models fields in
get_fieldsets
you need to overrideget_form
as well and set thefields
orexclude
attribute."
I think this has been fixed since the original report. I just tried the example and a field with blank=True
that was excluded using get_fieldsets
was not cleared as originally reported, nor was there a ValidationError
if the field had blank=False
.
Documentation for get_form
and get_fieldsets
has also been added.
"Another annoying inconsistency is that a form returned with get_form will not be respected by fieldsets argument on the ModelAdmin."
This was fixed in #18681.
Documents get_fieldsets and get_form, gives an example each and adds a note documenting the gotcha