15π
I have no idea why printing the property doesnβt give you want you just assigned (I guess may be that depends on where you print, exactly), but try overriding get_fieldsets
instead. The base implementation looks like this:
def get_fieldsets(self, request, obj=None): if self.declared_fieldsets: return self.declared_fieldsets form = self.get_formset(request).form return [(None, {'fields': form.base_fields.keys()})]
I.e. you should be able to just return your tuples.
EDIT by andybak. 4 years on and I found my own question again when trying to do something similar on another project. This time I went with this approach although modified slightly to avoid having to repeat fieldsets definition:
def get_fieldsets(self, request, obj=None):
# Add 'item_type' on add forms and remove it on changeforms.
fieldsets = super(ItemAdmin, self).get_fieldsets(request, obj)
if not obj: # this is an add form
if 'item_type' not in fieldsets[0][1]['fields']:
fieldsets[0][1]['fields'] += ('item_type',)
else: # this is a change form
fieldsets[0][1]['fields'] = tuple(x for x in fieldsets[0][1]['fields'] if x!='item_type')
return fieldsets
26π
I have some sample code from a recent project of mine that I believe may help you. In this example, super users can edit every field, while everyone else has the βdescriptionβ field excluded.
Note that I think itβs expected that you return a Form
class from get_form
, which could be why yours was not working quite right.
Hereβs the example:
class EventForm(forms.ModelForm):
class Meta:
model = models.Event
exclude = ['description',]
class EventAdminForm(forms.ModelForm):
class Meta:
model = models.Event
class EventAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
if request.user.is_superuser:
return EventAdminForm
else:
return EventForm
admin.site.register(models.Event, EventAdmin)
- Django 1.6 and django-registration: built-in authentication views not picked up
- Deploying Django (fastcgi, apache mod_wsgi, uwsgi, gunicorn)
8π
This is my solution:
class MyModelAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
if request.user.is_superuser:
self.exclude = ()
else:
self.exclude = ('field_to_exclude',)
return super(MyModelAdmin, self).get_form(request, obj=None, **kwargs)
Hope can help
6π
For creating customized admin forms we have defined a new class which can be used as mixin. The approach is quite flexible:
-
ModelAdmin: define a fieldset containing all fields
-
ModelForm: narrow the fields being shown
-
FlexibleModelAdmin: overriding get_fieldsets-method of ModelAdmin; returns a reduced fieldset that only contains the fields defined in the admin form
class FlexibleModelAdmin(object):
'''
adds the possibility to use a fieldset as template for the generated form
this class should be used as mix-in
'''
def _filterFieldset(self, proposed, form):
'''
remove fields from a fieldset that do not
occur in form itself.
'''
allnewfields = []
fields = form.base_fields.keys()
fieldset = []
for fsname, fdict in proposed:
newfields = []
for field in fdict.get('fields'):
if field in fields:
newfields.append(field)
allnewfields.extend(newfields)
if newfields:
newentry = {'fields': newfields}
fieldset.append([fsname, newentry])
# nice solution but sets are not ordered ;)
# don't forget fields that are in a form but were forgotten
# in fieldset template
lostfields = list(set(fields).difference(allnewfields))
if len(lostfields):
fieldset.append(['lost in space', {'fields': lostfields}])
return fieldset
def get_fieldsets(self, request, obj=None):
'''
Hook for specifying fieldsets for the add form.
'''
if hasattr(self, 'fieldsets_proposed'):
form = self.get_form(request, obj)
return self._filterFieldset(self.fieldsets_proposed, form)
else:
return super(FlexibleModelAdmin, self).get_fieldsets(request, obj)
In the admin model you define fieldsets_proposed which serves as template and contains all fields.
class ReservationAdmin(FlexibleModelAdmin, admin.ModelAdmin):
list_display = ['id', 'displayFullName']
list_display_links = ['id', 'displayFullName']
date_hierarchy = 'reservation_start'
ordering = ['-reservation_start', 'vehicle']
exclude = ['last_modified_by']
# considered by FlexibleModelAdmin as template
fieldsets_proposed = (
(_('General'), {
'fields': ('vehicle', 'reservation_start', 'reservation_end', 'purpose') # 'added_by'
}),
(_('Report'), {
'fields': ('mileage')
}),
(_('Status'), {
'fields': ('active', 'editable')
}),
(_('Notes'), {
'fields': ('note')
}),
)
....
def get_form(self, request, obj=None, **kwargs):
'''
set the form depending on the role of the user for the particular group
'''
if request.user.is_superuser:
self.form = ReservationAdminForm
else:
self.form = ReservationUserForm
return super(ReservationAdmin, self).get_form(request, obj, **kwargs)
admin.site.register(Reservation, ReservationAdmin)
In your model forms you can now define the fields to be excluded/included. get_fieldset() of the mixin-class makes sure that only the fields defined in the form are being returned.
class ReservationAdminForm(ModelForm):
class Meta:
model = Reservation
exclude = ('added_by', 'last_modified_by')
class ReservationUserForm(BaseReservationForm):
class Meta:
model = Reservation
fields = ('vehicle', 'reservation_start', 'reservation_end', 'purpose', 'note')
- Gunicorn sync workers spawning processes
- PIL β libjpeg.so.8: cannot open shared object file: No such file or directory
- Google App Engine Application Extremely slow
- Django: Faking a field in the admin interface?
- Celery β No module named five
4π
Donβt change the value of self attributes because itβs not thread-safe. You need to use whatever hooks to override those values.
- Django update on queryset to change ID of ForeignKey
- Managing multiple settings.py files
- How do I construct a Django form with model objects in a Select widget?
2π
In my case, with Django 2.1 you could do the following
In forms.py
class ObjectAddForm(forms.ModelForm):
class Meta:
model = Object
exclude = []
class ObjectChangeForm(forms.ModelForm):
class Meta:
model = Object
exclude = []
And then in the admin.py
from your.app import ObjectAddForm, ObjectChangeForm
class ObjectAdmin(admin.ModelAdmin):
....
def get_form(self, request, obj=None, **kwargs):
if obj is None:
kwargs['form'] = ObjectAddForm
else:
kwargs['form'] = ObjectChangeForm
return super().get_form(request, obj, **kwargs)
- Display query string values in django templates
- Return list of objects as dictionary with keys as the objects id with django rest framerwork
- Where do I import the `DoesNotExist` exception in Django 1.10 from?
- Error: command 'x86_64-linux-gnu-gcc' when installing mysqlclient
0π
You could make fieldsets
and form
properties and have them emit signals to get the desired forms/fieldsets.