I have a django app with the following class in my admin.py:
class SoftwareVersionAdmin(ModelAdmin):
fields = (\"product\", \"version_number\", \"descrip
Using formsets in Django 1.6 I ended up with the following:
def get_formsets(self, request, obj=None):
if obj is None:
# It's a new object
for field, fieldset in {'hide_me_from_the_first_fieldset': 0,
'me_from_the_second': 1,
'and_me_too': 1}.items():
self.fieldsets[fieldset][1]['fields'].remove(field)
return super().get_formsets(request, obj)
EDIT:
Perhaps a more intuitive way is to specify a separate add_fieldsets
property and do:
def get_formsets(self, request, obj=None):
if obj is None:
self.fieldsets = self.add_fieldsets
return super().get_formsets(request, obj)
This specific code did not work for me. I simply change it a little:
if obj: # obj is not None, so this is a change page
#kwargs['exclude'] = ['owner']
self.fields = ['id', 'family_name', 'status', 'owner']
else: # obj is None, so this is an add page
#kwargs['fields'] = ['id', 'family_name', 'status']
self.fields = ['id', 'family_name', 'status']
return super(YourAdmin, self).get_form(request, obj, **kwargs)
An easy way is to use fieldsets
for the Change Page and add_fieldsets
for the Add Page.
dpawlows' solution above is the clearest, I think.
However, I encountered an additional issue in that type of structure.
If change_view()
makes changes to the model, e.g. specifies readonly_fields
that have been filled in in add_view()
, these changes persist in add_view()
after change_view()
has been called. For example:
def add_view(self, request, extra_context=None):
return super().add_view(request)
def change_view(self, request, object_id, extra_context=None):
self.readonly_fields = ['name'] # this change persists in add_view()
return super().change_view(self, request, object_id)
In this case, after change_view()
has been called on any instance, invoking add_view()
will show readonly_fields
("name", in this case) set by change_view()
and thus protect these fields from filling in.
This can be solved by adding a 'roll back' assignment in add_view()
:
def add_view(self, request, extra_context=None):
self.readonly_fields = [] # 'roll back' for changes made by change_view()
return super().add_view(request)
I don't think it's a good idea to override fields
or exclude
or form
, because they are config attributes, so they would not initialize for every request.
I think the accepted answer by shanyu is a good solution.
Or we can use the method from UserAdmin:
def get_fieldsets(self, request, obj=None):
if not obj:
return self.add_fieldsets
return super(UserAdmin, self).get_fieldsets(request, obj)
Remember to assign the add_fieldsets
yourself. Unfortunately it doesn't fit my use case.
For Django 1.7. I don't know how they are implemented in other versions.
This is an old question but I wanted to add that the add_view and change_view methods can be modified for this purpose:
class SoftwareVersionAdmin(ModelAdmin):
...
def add_view(self,request,extra_content=None):
self.exclude = ('product','version_number',)
return super(SoftwareVersionAdmin,self).add_view(request)
def change_view(self,request,object_id,extra_content=None):
self.exclude = ('product','description',)
return super(SoftwareVersionAdmin,self).change_view(request,object_id)