I'm trying to write a dynamic form for models that allow users with different permissions to do different things. What I would like is for the below code to function properly, so that non-superusers can't edit any of the fields in the 'Merchant' block.
class CategoryModelAdmin(LWModelAdmin):
fieldsets = (
('Merchant', {'fields': ('merchant',) }),
('Category', { 'fields': ('name', 'parent',) }),
)
def get_form(self,request,obj=None, **kwargs):
if request.user.is_superuser:
self.exclude = []
else:
self.exclude = ['Merchant']
return super(CategoryModelAdmin,self).get_form(request, obj=None, **kwargs)
While I can achieve that effect via the code below, I'm really searching for the "right" way to do it and it feels like using exclude is the way to go, but I can't seem to get it right no matter what I try.
class CategoryModelAdmin(LWModelAdmin):
declared_fieldsets = None
admin_fieldsets = (
(None, {'fields': ('merchant',) }),
('Category', { 'fields': ('name', 'parent',) }),
)
restricted_fieldsets = (
('Category', { 'fields': ('name', 'parent',) }),
)
def get_fieldsets(self, request, obj=None):
if request.user.is_superuser:
fieldsets = self.admin_fieldsets
else:
fieldsets = self.restricted_fieldsets
return LWModelAdmin.fieldsets + fieldsets
def get_form(self, request, obj=None, **kwargs):
self.declared_fieldsets = self.get_fieldsets(request, obj)
return super(self.__class__, self).get_form(request, obj)
Your code is not thread-safe, you shouldn't set attributes on self (self.exclude
etc) in your custom ModelAdmin methods. Instead use kwargs of ModelAdmin.get_form
and InlineModelAdmin.get_formset
to get what you want.
Here's a simple example:
class CategoryModelAdmin(LWModelAdmin):
def get_form(self, request, obj=None, **kwargs):
if request.user.is_superuser:
kwargs['exclude'] = ['foo', 'bar',]
else:
kwargs['fields'] = ['foo',]
return super(CategoryModelAdmin, self).get_form(request, obj, **kwargs)
I'm not sure if this would be more or less of a hack, but have you considered this?
Create two different models, pointing to the same table. Each model can have it's own ModelAdmin class with whatever settings you want. Then use Django's permissions to make one of them invisible to non-administrators.
If you want to avoid duplicating code, you can derive both of your classes from some common base class you create.
The advantage is that you wouldn't be doing anything outside of what's written in the documentation. I don't think we're meant to be overwriting methods like get_form
and get_fieldsets
. If they're not truly part of the published API, those methods may change or be removed on day, and you could get owned in an upgrade.
Just a thought...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With