[Django]-Exclude fields in Django admin for users other than superuser

18๐Ÿ‘

โœ…

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!

๐Ÿ‘คyuvi

19๐Ÿ‘

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

๐Ÿ‘คMatt

10๐Ÿ‘

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๐Ÿ‘

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)
๐Ÿ‘คCaleb Bramwell

0๐Ÿ‘

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.

๐Ÿ‘คTzach

0๐Ÿ‘

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()
๐Ÿ‘คcwhisperer

Leave a comment