9

我需要编辑 django 管理面板。在我的应用程序中,超级用户可以添加用户并分配权限。当超级用户添加像人力资源经理这样的员工用户时,应用程序应该允许添加用户。有用。但我需要做的是当员工用户登录到管理面板时隐藏超级用户状态栏。我怎样才能做到这一点?我应该更改什么 Django 管理文件?如何?

4

3 回答 3

17

如果您希望您的超级用户仍然能够通过管理员添加其他超级用户,但不允许员工用户管理超级用户,您需要创建一个覆盖该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自定义管理中的方法并使用请求对象来确定哪个用户正在尝试访问它。

于 2013-09-21T02:22:17.767 回答
11

除了重新定义字段集,您还可以删除 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 发展,您将无需查看代码来修改字段集以与默认字段集保持一致。

在这个例子中,如果用户正在编辑自己,我也会删除该字段以避免失去一些权限。

编辑:添加 deepcopy 指令,否则使用第一个 request.user 执行代码的每个人都完成字段集更新(因为一个实例可以由两个不同的用户使用,具体取决于您的 Web 服务器配置)。

于 2014-02-18T16:32:58.717 回答
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”文件更新为“取消注册”和“注册”用户模型,并从字段集中删除“超级用户”字段。

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)

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

于 2013-04-20T04:34:04.300 回答