Using exclude with Django fields

I am trying to write a dynamic form for models that allow users with different permissions to do different things. I would like the code below to function correctly, so non-superusers cannot 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 this effect using the code below, I'm really looking for the β€œright” way to do this, and it seems to me that using exclude is the way to go, but I cannot figure out that it is correct 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) 
+4
source share
2 answers

Your code is not thread safe, you should not set self attributes ( self.exclude , etc.) in your custom ModelAdmin methods. Instead, use kwargs ModelAdmin.get_form and InlineModelAdmin.get_formset to get what you want.

Here is 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) 
+3
source

I'm not sure if this will be more or less due to a hack, but do you think it?

Create two different models, pointing to the same table. Each model can have its own ModelAdmin class with any settings you want. Then use Django permissions to make one of them invisible to non-administrators.

If you want to avoid code duplication, you can get classes from some common base class that you create.

The advantage is that you will not do anything other than what is written in the documentation. I do not think that we should rewrite methods such as get_form and get_fieldsets . If they are not part of the published API, these methods can be changed or removed daily, and you can access the update.

Just a thought ...

+1
source

All Articles