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



我有一个简单的MyUser类,PermissionsMixin . user.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',)}),
        )

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

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

如果我理解正确,您要做的是覆盖模型管理员的get_form方法。基于 django 文档中的示例,它看起来像这样:

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)

现在您可能需要稍微修改一下,也许还需要覆盖保存方法。不久前我做了类似的事情,它并不那么复杂(而且文档很棒)。

可能有一个更简单的解决方案,但你的问题有点笼统,你没有分享你的用户模型,所以我不能确切地告诉你如何解决这个问题。我希望这有帮助!

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

它将当前请求和对象(如果有)作为参数。您可以在请求参数上进行检查,以查看他们是否是超级用户并检查

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

根据Django Docs的说法,正确的方法是为超级用户创建一个ModelForm,为普通用户创建一个ModelForm。然后,在模型管理员的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)

从 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。

我以这种方式解决了它,灵感来自以前的答案。在我的示例中,只有超级用户可以创建超级用户。如果不是超级用户,则表单中的复选框将丢失。它对我有用,我希望它是正确的:

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

最新更新