simple ui 自定义用户权限菜单

发布时间 2023-12-20 14:12:31作者: 腐汝

前因:

本来不想改simple ui的菜单的,但是有些洁癖真的忍不了,就比如将的group的概念改成了自己想象中的role之后,在默认的simple UI中自带的group和role不在一个菜单下面,也尝试自定义了group,后果就是很多方法都需要自己去实现,爆炸。

实现:

1)模型

我的权限和菜单比较有个性,不建议使用我这种方式,因为改起来比较麻烦,所以就不想改。

class MyUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(verbose_name='邮件地址', max_length=255, unique=True)
    phone = models.CharField('手机号码', max_length=20, help_text='手机号码')
    date_of_birth = models.DateTimeField('创建时间', default=timezone.now)
    name = models.CharField('名字', max_length=20)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField('是否可以登录后台', default=False)  # 这个配置决定用户是否可以登录后台,不能所有权限都给superuser

    objects = MyUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['name', 'phone']

    def __str__(self):
        return self.name

    @property
    def is_staff(self):
        return self.is_admin

    class Meta:  # 给模型增加权限
        verbose_name = "用户"
        verbose_name_plural = "用户们"
        permissions = [
            ("list_user", "Can change the status of tasks"),
            ("close_user", "Can remove a task by setting its status as closed"),
        ]


class Menu(models.Model):
    """
    菜单
    """
    type_choice = (
        ('interface', '接口'),
        ('menu', '菜单')
    )
    name = models.CharField(max_length=30, unique=True, db_index=True, verbose_name="菜单名")
    icon = models.CharField(max_length=50, null=True, blank=True, verbose_name="图标")
    path = models.CharField(max_length=255, null=True, blank=True, verbose_name="链接地址")
    type = models.CharField(max_length=30, null=True, blank=True, db_index=True, choices=type_choice,
                            verbose_name='类型')
    is_show = models.BooleanField(default=True, db_index=True, verbose_name="是否显示")
    sort = models.IntegerField(null=True, blank=True, db_index=True, verbose_name="排序标记")
    pid = models.ForeignKey('self', null=True, blank=True, on_delete=models.SET_NULL, verbose_name="父菜单")

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = '菜单'
        verbose_name_plural = verbose_name
        ordering = ['id']

 

2)simple ui的菜单配置

SIMPLEUI_CONFIG = {
    'dynamic': False,
    'menus': [],
}

3)在中间件中控制菜单

class MenuMiddleware(MiddlewareMixin):
    """
    自定义左边的菜单栏
    """

    def process_request(self, request):
        current_user = request.user
        perms = current_user.get_all_permissions()
        perms_list = set()  # /admin/app_label/model_name/, 用这种方式模型的命名规则一定要规范,否则匹配失败
        for permission in perms:
            app = permission.split('.')[0]
            module = permission.split('.')[1].split('_')[1]
            path = f'/admin/{app}/{module}/'
            perms_list.add(path)

        from user.models import Menu  # 用户的权限里面有没有这个菜单
        menu_list = []
        for _m in Menu.objects.filter(type__exact='menu',
                                      is_show__exact=True).order_by('sort'):
            inter_queryset = _m.menu_set.all().filter(is_show__exact=True).order_by('sort')
            men_dict = {
                'name': _m.name,
                'icon': _m.icon,
                'models': []
            }
            for inter in inter_queryset:
                if inter.path in perms_list:
                    men_dict['models'].append({
                        'name': inter.name,
                        'icon': inter.icon,
                        'url': inter.path
                    })
            if len(men_dict['models']) > 0:
                menu_list.append(men_dict)
            settings.SIMPLEUI_CONFIG['menus'] = menu_list
        return None

 

4) 菜单的管理