DjangoAdmin自定义权限

如标题。最近在研究xadmin,发现文档确实比较少,自己只能连滚带爬~

起因

因为想做一个审批的功能,用xadmin acrtion来实现。本来想用模块现有“change”字段控制权限,但是发现使用“change”字段控制权限的话,会把自带的 “delete” action 暴露出来,这不是我想要的。 所以在模块里添加了一个“approver”字段,用以控制权限。

代码

首先修改模块的 “Meta”,增加权限字段。

class TaskApprove(Task):
    class Meta:
        proxy = True
        verbose_name = u'审批'
        verbose_name_plural = verbose_name
        permissions = (
            ("approve","审批:用户任务"),
        )

然后刷新一下数据库,会在用户管理的界面中看到我们新加的权限。 接下来在adminx.py中创建自己的action,并在你的管理类中添加。

from xadmin.plugins.actions import BaseActionView
class MyAction(BaseActionView):
    action_name = u'accept'
    model_perm = 'approve'
    description =  '同意'
    def do_action(self, queryset):
        for obj in queryset:
	        ##你的操作
            print(obj)
        return HttpResponse('您已同意')
class TaskApproveSettings(ViewOnlyMixin):
    actions = [MyAction,]
    list_display = ['name','targets','services','create_by']
xadmin.site.register(TaskApprove,TaskApproveSettings)

下面是重点, 因为xadmin中的权限检测是写死的 只有 “view\change\delete\add”,而我们添加了一个“approve字段”, 这会导致报错 – “keyerro” 。 所以接下来我们覆盖一下xadmin中的方法,添加一个方法。 *** 不知道为什么前几次以继承覆盖的方式没有成功~~*** 在控制类TaskApproveSettings中添加。 首先添加一个方法,用来获取是否有权限

def has_approve_permission(self):
    codename = get_permission_codename('approve', self.opts)
    return ('approve' not in self.remove_permissions) and self.user.has_perm('%s.%s' % (self.app_label, codename))

接下来修改get_model_perms 方法,将我们的权限添加进去

    def get_model_perms(self):
        """
        Returns a dict of all perms for this model. This dict has the keys
        ``add``, ``change``, and ``delete`` mapping to the True/False for each
        of those actions.
        """
        return {
            'view': self.has_view_permission(),
            'add': self.has_add_permission(),
            'change': self.has_change_permission(),
            'delete': self.has_delete_permission(),
            'approve': self.has_approve_permission()
        }

最后是这样的

from xadmin.plugins.actions import BaseActionView
from django.shortcuts import HttpResponse
from django.contrib.auth import get_permission_codename
class ActionApproveAccept(BaseActionView):
    action_name = u'accept'
    model_perm = 'approve'
    description =  '同意'
    global_actions = []
    def do_action(self, queryset):
        for obj in queryset:
            print(obj)
        return HttpResponse('您已同意')

class ActionApproveReject(BaseActionView):
    action_name = u'reject'
    model_perm = 'approve'
    description =  '拒绝'
    global_actions = []
    def do_action(self, queryset):
        for obj in queryset:
            print(obj)
        return HttpResponse('您已拒绝')
class TaskApproveSettings(ViewOnlyMixin):
    actions = [ActionApproveAccept,ActionApproveReject]

    list_display = ['name','targets','services','create_by']
    readonly_fields = TaskFields.create+TaskFields.params+TaskFields.approve
    form_layout = (
        Main(
            Fieldset('',
                     *TaskFields.create,
                     css_class='unsort no_title'
                     ),

            Fieldset(('参数'),
                     *TaskFields.params
                     ),
        ),
        Side(
            Fieldset(('审批状态'),
                     *TaskFields.approve
                     ),
        )
    )
    def get_model_perms(self):
        return {
            'view': self.has_view_permission(),
            'add': self.has_add_permission(),
            'change': self.has_change_permission(),
            'delete': self.has_delete_permission(),
            'approve': self.has_approve_permission()
        }
    def has_approve_permission(self):
        codename = get_permission_codename('approve', self.opts)
        return ('approve' not in self.remove_permissions) and self.user.has_perm('%s.%s' % (self.app_label, codename))

重启服务就好啦!


我仅做了目前这些,暂时没有发现问题。如果后面发现问题我会继续补充,另外大家如果有更好的方法,欢迎留言纠正~!