Django:当员工用户登录时,从Django管理面板中删除超级用户复选框

9

我需要编辑Django的管理员面板。在我的应用程序中,超级用户可以添加用户并分配权限。当超级用户添加HR经理等员工用户时,应用程序应允许添加用户。这个功能已经实现了。但是我需要做的是,当员工用户登录到管理面板时,隐藏超级用户状态栏。我该怎么做?我需要更改哪个Django管理员文件?如何操作?


嘿@Lahiruzz,您提供的信息可能有点模糊。您能否向我描述一下“超级用户状态栏”是什么?它是整个管理面板顶部的默认青色(ish)栏吗? - Tim Selaty Jr.
当用户在Django管理面板中创建时,我们可以给予权限。在权限下,您可以看到超级用户复选框,我想在员工用户登录系统但不是超级用户时隐藏该复选框。 - Lahiruzz
http://www.mahner.org/posts/separating-staff-and-user-accounts-in-djangos-admin/ - catherine
4个回答

18

如果您希望超级用户仍然能够通过管理员添加其他超级用户,但不允许工作人员用户管理超级用户,则需要创建一个自定义管理员来覆盖get_fieldsets方法。这可以放在您的admin.py文件中:

from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from django.utils.translation import ugettext, ugettext_lazy as _

class MyUserAdmin(UserAdmin):
    def get_fieldsets(self, request, obj=None):
        if not obj:
            return self.add_fieldsets

        if request.user.is_superuser:
            perm_fields = ('is_active', 'is_staff', 'is_superuser',
                           'groups', 'user_permissions')
        else:
            # modify these to suit the fields you want your
            # staff user to be able to edit
            perm_fields = ('is_active', 'is_staff')

        return [(None, {'fields': ('username', 'password')}),
                (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
                (_('Permissions'), {'fields': perm_fields}),
                (_('Important dates'), {'fields': ('last_login', 'date_joined')})]

按照以下步骤注销Django的用户管理员并注册您的新用户管理员:

admin.site.unregister(User)
admin.site.register(User, MyUserAdmin)

对于任何一个你想要为一组用户提供不同的字段集合的模型,你都可以采取类似的方法 -- 只需要覆盖你的自定义管理员中的get_fieldsets方法,并使用请求对象来确定尝试访问它的用户即可。


14

你不必重新定义 fieldsets,只需删除 is_superuser 字段:

from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from copy import deepcopy

class UserAdmin(UserAdmin):

    def get_fieldsets(self, request, obj=None):
        fieldsets = super(UserAdmin, self).get_fieldsets(request, obj)
        if not obj:
            return fieldsets

        if not request.user.is_superuser or request.user.pk == obj.pk:
            fieldsets = deepcopy(fieldsets)
            for fieldset in fieldsets:
                if 'is_superuser' in fieldset[1]['fields']:
                    if type(fieldset[1]['fields']) == tuple :
                        fieldset[1]['fields'] = list(fieldset[1]['fields'])
                    fieldset[1]['fields'].remove('is_superuser')
                    break

        return fieldsets

User = get_user_model()
admin.site.unregister(User)
admin.site.register(User, UserAdmin)

主要优点是您可以保留默认字段集。如果django.contrib.admin发生变化,您无需重新审查代码以修改字段集以与默认字段集保持一致。

在这个例子中,我还会删除字段,如果用户正在编辑自己,以避免某些失去权限的情况。

编辑:添加深层复制指令,否则字段集更新将针对第一个执行该代码的request.user,因为一个实例可能被两个不同的用户使用,具体取决于您的Web服务器配置。


这对我有用,但是导入语句是 from django.contrib.auth.admin import UserAdmin | from django.contrib.auth.models import User - Cristian Sepulveda
谢谢,我已经修复了。但是你不应该直接导入用户模型:它可能是另一个被使用的模型。使用 get_user_model 可以避免这个问题。 - DylannCordel

8
为了从Django Admin的"编辑用户"页面中删除"超级用户"复选框,重要的是要了解"超级用户"复选框来自何处以及如何来的。
在您的Django安装中,一个名为django.contrib.auth.forms的文件调用类class UserChangeForm(forms.ModelForm)。它读取的模型文件是django.contrib.auth.models下的class User(models.Model)类。实际上,django.contrib.auth.admin文件通过手动fieldset参数传递在模型中找到的字段。
class UserAdmin(admin.ModelAdmin):
fieldsets = (
    (None, {'fields': ('username', 'password')}),

    (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),        
    (_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
                                   'groups', 'user_permissions')}),
    (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
)

最好的方法是更新本地的“admin.py”文件,以“注销”并“注册”用户模型,并从字段集中删除“superuser”字段。

from django.db import transaction
from django.conf import settings
from django.contrib import admin
from django.contrib.auth.forms import (UserCreationForm, UserChangeForm,
    AdminPasswordChangeForm)
from django.contrib.auth.models import User
from django.contrib import messages
from django.core.exceptions import PermissionDenied
from django.http import HttpResponseRedirect, Http404
from django.shortcuts import get_object_or_404
from django.template.response import TemplateResponse
from django.utils.html import escape
from django.utils.decorators import method_decorator
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext, ugettext_lazy as _
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.debug import sensitive_post_parameters

csrf_protect_m = method_decorator(csrf_protect)

### Unregister the existing User model from the admin
admin.site.unregister(User)

class UserAdmin(admin.ModelAdmin):
    add_form_template = 'admin/auth/user/add_form.html'
    change_user_password_template = None
    fieldsets = (
        (None, {'fields': ('username', 'password')}),

        (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),        

        ###################################
        #### CHANGE THIS RIGHT HERE #######        
        (_('Permissions'), {'fields': ('is_active', 'is_staff', 
                                       'groups', 'user_permissions')}),
        ####################################

        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('username', 'password1', 'password2')}
        ),
    )
    form = UserChangeForm
    add_form = UserCreationForm
    change_password_form = AdminPasswordChangeForm
    list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
    list_filter = ('is_staff', 'is_superuser', 'is_active')
    search_fields = ('username', 'first_name', 'last_name', 'email')
    ordering = ('username',)
    filter_horizontal = ('user_permissions',)

    def get_fieldsets(self, request, obj=None):
        if not obj:
            return self.add_fieldsets
        return super(UserAdmin, self).get_fieldsets(request, obj)

    def get_form(self, request, obj=None, **kwargs):
        """
        Use special form during user creation
        """
        defaults = {}
        if obj is None:
            defaults.update({
                'form': self.add_form,
                'fields': admin.util.flatten_fieldsets(self.add_fieldsets),
            })
        defaults.update(kwargs)
        return super(UserAdmin, self).get_form(request, obj, **defaults)

    def get_urls(self):
        from django.conf.urls import patterns
        return patterns('',
            (r'^(\d+)/password/$',
             self.admin_site.admin_view(self.user_change_password))
        ) + super(UserAdmin, self).get_urls()

    @sensitive_post_parameters()
    @csrf_protect_m
    @transaction.commit_on_success
    def add_view(self, request, form_url='', extra_context=None):
        # It's an error for a user to have add permission but NOT change
        # permission for users. If we allowed such users to add users, they
        # could create superusers, which would mean they would essentially have
        # the permission to change users. To avoid the problem entirely, we
        # disallow users from adding users if they don't have change
        # permission.
        if not self.has_change_permission(request):
            if self.has_add_permission(request) and settings.DEBUG:
                # Raise Http404 in debug mode so that the user gets a helpful
                # error message.
                raise Http404(
                    'Your user does not have the "Change user" permission. In '
                    'order to add users, Django requires that your user '
                    'account have both the "Add user" and "Change user" '
                    'permissions set.')
            raise PermissionDenied
        if extra_context is None:
            extra_context = {}
        defaults = {
            'auto_populated_fields': (),
            'username_help_text': self.model._meta.get_field('username').help_text,
        }
        extra_context.update(defaults)
        return super(UserAdmin, self).add_view(request, form_url,
                                               extra_context)

    @sensitive_post_parameters()
    def user_change_password(self, request, id, form_url=''):
        if not self.has_change_permission(request):
            raise PermissionDenied
        user = get_object_or_404(self.queryset(request), pk=id)
        if request.method == 'POST':
            form = self.change_password_form(user, request.POST)
            if form.is_valid():
                form.save()
                msg = ugettext('Password changed successfully.')
                messages.success(request, msg)
                return HttpResponseRedirect('..')
        else:
            form = self.change_password_form(user)

        fieldsets = [(None, {'fields': form.base_fields.keys()})]
        adminForm = admin.helpers.AdminForm(form, fieldsets, {})

        context = {
            'title': _('Change password: %s') % escape(user.username),
            'adminForm': adminForm,
            'form_url': mark_safe(form_url),
            'form': form,
            'is_popup': '_popup' in request.REQUEST,
            'add': True,
            'change': False,
            'has_delete_permission': False,
            'has_change_permission': True,
            'has_absolute_url': False,
            'opts': self.model._meta,
            'original': user,
            'save_as': False,
            'show_save': True,
        }
        return TemplateResponse(request, [
            self.change_user_password_template or
            'admin/auth/user/change_password.html'
        ], context, current_app=self.admin_site.name)

    def response_add(self, request, obj, post_url_continue='../%s/'):
        """
        Determines the HttpResponse for the add_view stage. It mostly defers to
        its superclass implementation but is customized because the User model
        has a slightly different workflow.
        """
        # We should allow further modification of the user just added i.e. the
        # 'Save' button should behave like the 'Save and continue editing'
        # button except in two scenarios:
        # * The user has pressed the 'Save and add another' button
        # * We are adding a user in a popup
        if '_addanother' not in request.POST and '_popup' not in request.POST:
            request.POST['_continue'] = 1
        return super(UserAdmin, self).response_add(request, obj,
                                                   post_url_continue)

admin.site.register(User, UserAdmin)

通过注销管理员类并重新注册,您可以覆盖它传递到“编辑用户”页面字段集中的字段。希望这能帮到您!

嘿!我在添加用户时无法提供超级用户选项..这可能吗? - Deepanshu Goyal

0
我刚刚有同样的问题,经过一些研究,我更倾向于以下的答案:
def get_readonly_fields(self, request, obj=None):
    fields = ["date_joined", "last_login"]
    if not request.user.is_superuser:
        fields.append("is_superuser")
    return fields

将此内容添加到您的自定义UserAdmin中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接