Search code examples
djangofieldadminediting

Show different model admin list_display and fields set for different user groups


In django I have superuser and group of content editors.

When I edit model as superuser I want be able to edit all fields. And if someone logged in as editor I want to allow him to edit only specific fields.

I have done that with get_form method:

class VideoAdmin(admin.ModelAdmin):    
    editor_fields = ('description','description_rewrited')

    def get_form(self, request, obj=None, **kwargs):
        if not hasattr(request.user, 'perms_list'):
            request.user.perms_list = request.user.groups.values_list('name',flat=True)

        if 'video_description_rewriter' in request.user.perms_list:
            print('rewrite fields to normal')
            self.fields = self.normaluser_fields

        return super(VideoAdmin, self).get_form(request, obj, **kwargs)

It works for me. But when I open video for editing as regular editor it changes superuser fields set to editors fields set.

  1. Open admin model as superuser - http://joxi.ru/zAN5wWMIVjz429
  2. Open admin model as editor - http://joxi.ru/p27LJPZiDNgeA7
  3. Now superuser has the same fields set as editor - http://joxi.ru/L21jko5TW0ydAX

I assume that there is some kind of template caching?


Solution

  • You're setting self.fields to self.normaluser_fields when user is editor, but you aren't setting self.fields back to default value when user is admin. ModelAdmin objects are created on application load and they're shared between all users!

    Changing fields back to default value when admin enters page won't solve problem in 100% percent. When admin and non-admin user will try to enter edit page in same time, race condition might occur. Both of them can get same fields.

    Instead of rewritting get_form, you can do it simpler by rewritting get_fields method:

        def get_fields(self, request):
            if not hasattr(request.user, 'perms_list'):
                request.user.perms_list = request.user.groups.values_list('name',flat=True)
    
            if 'video_description_rewriter' in request.user.perms_list:
                print('rewrite fields to normal')
                return self.normaluser_fields
    
            return self.fields
    

    That method won't overwrite any values in ModelAdmin object, so change will be only visible for one user.