Exclude fields in Django admin for users other than superuser

后端 未结 6 1134
孤独总比滥情好
孤独总比滥情好 2021-02-04 04:34

I have a simple MyUser class with PermissionsMixin. user.is_superuser equals True only for superusers. I\'d like to be able t

相关标签:
6条回答
  • 2021-02-04 05:10

    According to Django Docs, the correct way is to create a ModelForm for superusers and another for normal users. Then you specify each form in the get_form method of your ModelAdmin:

    class MyModelAdmin(admin.ModelAdmin):
        def get_form(self, request, obj=None, **kwargs):
            if request.user.is_superuser:
                kwargs['form'] = MySuperuserForm
            else:
                kwargs['form'] = MyNormalForm
            return super(MyModelAdmin, self).get_form(request, obj, **kwargs)
    
    0 讨论(0)
  • 2021-02-04 05:13

    If I understand you correctly, what you want to do is override the get_form method for the ModelAdmin. Base on the example from django documentation, it would look something like this:

    class MyUserAdmin(admin.ModelAdmin):
        def get_form(self, request, obj=None, **kwargs):
            self.exclude = []
            if not request.user.is_superuser:
                self.exclude.append('Permissions') #here!
            return super(MyUserAdmin, self).get_form(request, obj, **kwargs)
    

    Now you might need to hack around a little and maybe override the save method as well. I did something similar not long ago, it's not so complicated (and the docs are fantastic).

    There might be a simpler solution but your question is kinda general and you didn't share your user model, so I can't tell you exactly how to work this out. I hope this helps!

    0 讨论(0)
  • 2021-02-04 05:17

    Django now has a get_exclude method on ModelAdmin for excluding fields programmatically.

    It takes the current request and the object (if any) as argument. You can put a check there on the request argument to see if they're a superuser and check

    class MyModelAdmin(admin.ModelAdmin):
        def get_exclude(self, request, obj=None):
            excluded = super().get_exclude(request, obj) or [] # get overall excluded fields
    
            if not request.user.is_superuser: # if user is not a superuser
                return excluded + ['extra_field_to_exclude']
    
            return excluded # otherwise return the default excluded fields if any
    
    0 讨论(0)
  • 2021-02-04 05:19

    Starting Django 1.7 you can replace the base class of your model admin with something like:

    class SuperuserAwareModelAdmin(admin.ModelAdmin):
        superuser_fields = None
        superuser_fieldsets = None
    
        def get_fieldsets(self, request, obj = None):
            if request.user.is_superuser and self.superuser_fieldsets:
                return (self.fieldsets or tuple()) + self.superuser_fieldsets
            return super(SuperuserAwareModelAdmin, self).get_fieldsets(request, obj)
    
        def get_fields(self, request, obj = None):
            if request.user.is_superuser and self.superuser_fields:
                return (self.fields or tuple()) + self.superuser_fields
            return super(SuperuserAwareModelAdmin, self).get_fields(request, obj)
    

    Example:

    class MyModelAdmin(SuperuserAwareModelAdmin):
        superuser_fieldsets = (
            (_('Permissions'), {'fields': ('is_staff', )}),
        )
    

    The SuperuserAwareModelAdmin base class can also be created as a mixin.

    0 讨论(0)
  • 2021-02-04 05:20

    Accepted answer is close but as others point out, get_form is called multiple times on the same instance of the Admin model and the instance is reused, so you can end up with fields repeated or other users seeing the fields after self.fields is modified. Try this out in Django <=1.6:

    class MyAdmin(admin.ModelAdmin):
    
        normaluser_fields = ['field1','field2']
        superuser_fields = ['special_field1','special_field2']
    
        def get_form(self, request, obj=None, **kwargs):
            if request.user.is_superuser:
                self.fields = self.normaluser_fields + self.superuser_fields
            else:
                self.fields = self.normaluser_fields
    
            return super(MyAdmin, self).get_form(request, obj, **kwargs)
    

    Looks like, Django 1.7 introduces a get_fields() method you can override which is a much nicer approach:

    https://github.com/django/django/blob/d450af8a2687ca2e90a8790eb567f9a25ebce85b/django/contrib/admin/options.py#L276

    0 讨论(0)
  • 2021-02-04 05:29

    I solved it this way inspired by previous answers. In my example only a superuser may create a superuser. If it is not superuser the checkbox in the form is missing. It works for me and I hope it is correct:

        def get_form(self, form_class=form_class):
    
            if self.request.user.is_superuser is False:
                self.form_class.base_fields.pop('is_superuser')
            return super(AccountCreateView, self).get_form()
    
    0 讨论(0)
提交回复
热议问题