为超级用户以外的用户排除Django admin中的字段

时间:2013-10-05 21:45:13

标签: python django

我有一个简单的MyUser班级PermissionsMixinuser.is_superuser仅对超级用户等于True。我希望能够在admin.py

中做类似的事情
    if request.user.is_superuser:
        fieldsets = (
            (None, {'fields': ('email', 'password')}),
            ('Permissions', {'fields': ('is_admin','is_staff')}),
            ('Place', {'fields': ('place',)}),
            ('Important dates', {'fields': ('last_login',)}),
        )
    else:
        fieldsets = (
            (None, {'fields': ('email', 'password')}),
            #('Permissions', {'fields': ('is_admin','is_staff')}),
            ('Place', {'fields': ('place',)}),
            ('Important dates', {'fields': ('last_login',)}),
        )

基本上我希望我的用户能够创建其他用户,但不能授予他们管理员或资源权限。只有超级用户才能做到这一点。

6 个答案:

答案 0 :(得分:17)

接受的答案很接近,但正如其他人指出的那样,在同一个Admin模型实例上多次调用get_form并重复使用该实例,因此最终可能会重复使用字段或其他用户在self.fields之后看到字段被修改了。在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)

看起来,Django 1.7引入了一个可以覆盖的get_fields()方法,这是一种更好的方法:

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

答案 1 :(得分:16)

如果我理解正确,您要做的是覆盖ModelAdmin的get_form方法。基于the example from django documentation,它看起来像这样:

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)

现在你可能需要稍微破解一下,也可以覆盖save方法。我不久前做过类似的事情,并不是那么复杂(而且文档非常棒)。

可能有一个更简单的解决方案,但您的问题有点笼统,而且您没有共享您的用户模型,因此我无法确切地告诉您如何解决这个问题。我希望这有帮助!

答案 2 :(得分:1)

Django现在在ModelAdmin上有一个get_exclude方法,用于以编程方式排除字段。

它将当前请求和对象(如果有)作为参数。您可以在request参数上检查一下他们是否是超级用户,然后检查

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

答案 3 :(得分:0)

根据Django Docs,正确的方法是为超级用户创建一个ModelForm,为普通用户创建另一个。然后在ModelAdmin的get_form方法中指定每个表单:

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)

答案 4 :(得分:0)

启动Django 1.7,您可以使用以下内容替换模型管理员的基类:

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)

示例:

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

SuperuserAwareModelAdmin基类也可以创建为mixin。

答案 5 :(得分:0)

我是根据以前的答案通过这种方式解决的。在我的示例中,只有超级用户才能创建超级用户。如果不是超级用户,则缺少表单中的复选框。它对我有用,我希望它是正确的:

    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()