Django+vue3权限菜单rabc设计和动态路由

这篇具有很好参考价值的文章主要介绍了Django+vue3权限菜单rabc设计和动态路由。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本次是基于Django和vue实现

github源码:nineaiyu/xadmin-server: xadmin-基于Django+vue3的rbac权限管理系统 (github.com)

Django+vue3权限菜单rabc设计和动态路由,Xadmin,技能,Django,django,python,后端,vue,RBAC,权限控制

服务器设计及部分代码 

权限控制的话,可以基于Django的permission进行控制,并通过访问api的URL操作

核心代码如下

import re

from django.conf import settings
from rest_framework.exceptions import PermissionDenied, NotAuthenticated
from rest_framework.permissions import BasePermission

from system.models import Menu


def get_user_permission(user_obj):
    menu = []
    if user_obj.roles:
        menu_obj = Menu.objects.filter(userrole__in=user_obj.roles.all()).distinct()
        menu = menu_obj.filter(is_active=True, menu_type=2).values('path', 'component').all().distinct()
    return menu


class IsAuthenticated(BasePermission):
    """
    Allows access only to authenticated users.
    """

    def has_permission(self, request, view):
        auth = bool(request.user and request.user.is_authenticated)
        if auth:
            if request.user.is_superuser:
                return True
            url = request.path_info
            for w_url in settings.PERMISSION_WHITE_URL:
                if re.match(w_url, url):
                    return True
            permission_data = get_user_permission(request.user)
            for p_data in permission_data:
                if p_data.get('component') == request.method and re.match(f"/{p_data.get('path')}", url):
                    return True
            raise PermissionDenied('权限不足')
        else:
            raise NotAuthenticated('未授权认证')

因此,需要对menu表进行设计,由于涉及到了前端vue路由,因此,menu模型字段比较多,如下

class DbBaseModel(models.Model):
    created_time = models.DateTimeField(auto_now_add=True, verbose_name="添加时间")
    updated_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    description = models.CharField(max_length=128, verbose_name="描述信息", null=True, blank=True)

    class Meta:
        abstract = True


class MenuMeta(DbBaseModel):
    title = models.CharField(verbose_name="菜单名称", max_length=256, null=True, blank=True)
    icon = models.CharField(verbose_name="菜单图标", max_length=256, null=True, blank=True)
    r_svg_name = models.CharField(verbose_name="菜单右侧额外图标iconfont名称,目前只支持iconfont", max_length=256,
                                  null=True, blank=True)
    is_show_menu = models.BooleanField(verbose_name="是否显示该菜单", default=True)
    is_show_parent = models.BooleanField(verbose_name="是否显示父级菜单", default=False)
    is_keepalive = models.BooleanField(verbose_name="是否开启页面缓存", default=False,
                                       help_text='开启后,会保存该页面的整体状态,刷新后会清空状态')
    frame_url = models.CharField(verbose_name="内嵌的iframe链接地址", max_length=256, null=True, blank=True)
    frame_loading = models.BooleanField(verbose_name="内嵌的iframe页面是否开启首次加载动画", default=False)

    transition_enter = models.CharField(verbose_name="当前页面进场动画", max_length=256, null=True, blank=True)
    transition_leave = models.CharField(verbose_name="当前页面离场动画", max_length=256, null=True, blank=True)

    is_hidden_tag = models.BooleanField(verbose_name="当前菜单名称或自定义信息禁止添加到标签页", default=False)
    dynamic_level = models.IntegerField(verbose_name="显示标签页最大数量", default=1)

    class Meta:
        verbose_name = "菜单元数据"
        verbose_name_plural = "菜单元数据"
        ordering = ("-created_time",)

    def __str__(self):
        return f"{self.title}-{self.description}"


class Menu(DbBaseModel):
    parent = models.ForeignKey(to='Menu', on_delete=models.SET_NULL, verbose_name="父节点", null=True, blank=True)

    menu_type_choices = ((0, '目录'), (1, '菜单'), (2, '权限'))
    menu_type = models.SmallIntegerField(choices=menu_type_choices, default=0, verbose_name="节点类型")

    name = models.CharField(verbose_name="组件英文名称", max_length=128, unique=True)
    rank = models.IntegerField(verbose_name="菜单顺序", default=9999)
    path = models.CharField(verbose_name="路由地址", max_length=256)
    component = models.CharField(verbose_name="组件地址", max_length=256, null=True, blank=True)
    is_active = models.BooleanField(verbose_name="是否启用该菜单", default=True)
    meta = models.OneToOneField(to=MenuMeta, on_delete=models.CASCADE, verbose_name="菜单元数据")
    method_choices = (('GET', 'get'), ('POST', 'post'), ('PUT', 'put'), ('DELETE', 'delete'))

    def delete(self, using=None, keep_parents=False):
        if self.meta:
            self.meta.delete(using, keep_parents)
        super().delete(using, keep_parents)

    class Meta:
        verbose_name = "菜单信息"
        verbose_name_plural = "菜单信息"
        ordering = ("-created_time",)

    def __str__(self):
        return f"{self.name}-{self.menu_type}-{self.meta.title}"

最重要的menu表已经设计完成,那么接下来就更简单了,还需要一个获取所有路由的方法,当添加权限的时候,可以方便的选择相应的路由权限

import re
from collections import OrderedDict

from django.conf import settings
from django.urls import URLPattern, URLResolver
from django.utils.module_loading import import_string


def check_show_url(url):
    for prefix in settings.PERMISSION_SHOW_PREFIX:
        if re.match(prefix, url):
            return True


def recursion_urls(pre_namespace, pre_url, urlpatterns, url_ordered_dict):
    """递归去获取URL
    :param pre_namespace: namespace前缀,以后用户拼接name
    :param pre_url: url前缀,以后用于拼接url
    :param urlpatterns: 路由关系列表
    :param url_ordered_dict: 用于保存递归中获取的所有路由
    """
    for item in urlpatterns:
        if isinstance(item, URLPattern):
            if not item.name:
                continue

            if pre_namespace:
                name = "%s:%s" % (pre_namespace, item.name)
            else:
                name = item.name
            if not item.name:
                raise Exception('URL路由中必须设置name属性')
            url = pre_url + item.pattern.regex.pattern.lstrip('^')
            # url = url.replace('^', '').replace('$', '')

            if check_show_url(url):
                url_ordered_dict[name] = {'name': name, 'url': url}

        elif isinstance(item, URLResolver):  # 路由分发,递归操作
            if pre_namespace:
                if item.namespace:
                    namespace = "%s:%s" % (pre_namespace, item.namespace)
                else:
                    namespace = item.namespace
            else:
                if item.namespace:
                    namespace = item.namespace
                else:
                    namespace = None
            recursion_urls(namespace, pre_url + item.pattern.regex.pattern.lstrip('^'), item.url_patterns,
                           url_ordered_dict)


def get_all_url_dict(pre_url='/'):
    """
       获取项目中所有的URL(必须有name别名)
    """
    url_ordered_dict = OrderedDict()
    md = import_string(settings.ROOT_URLCONF)
    url_ordered_dict['#'] = {'name': '#', 'url': '#'}
    recursion_urls(None, pre_url, md.urlpatterns, url_ordered_dict)  # 递归去获取所有的路由
    return url_ordered_dict.values()

前端设计

前端代码已经开源,GitHub如下: nineaiyu/xadmin-client: xadmin-基于Django+vue3的rbac权限管理系统 (github.com)​​​​​​​q

前端是基于pure-admin二次开发的, 省去了前端开发,直接上手。

Django+vue3权限菜单rabc设计和动态路由,Xadmin,技能,Django,django,python,后端,vue,RBAC,权限控制

 文章来源地址https://www.toymoban.com/news/detail-527253.html

到了这里,关于Django+vue3权限菜单rabc设计和动态路由的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue3-实战-12-管理后台-权限管理之菜单管理模块-首页-主题颜色-暗黑模式

    目录 1-列表页面功能开发 1.1-需求原型分析 1.2-接口和数据类型定义 1.3-获取服务端数据渲染页面 2-新增编辑菜单 2.1-原型需求分析 2.2-表单数据收集和页面结构开发 2.3-提交或者取消 3-删除菜单 4-首页开发 5-暗黑模式的切换和主题颜色 5.1-暗黑模式 5.2-主题颜色切换       我们

    2024年02月10日
    浏览(56)
  • Vue-根据角色获取菜单动态添加路由

    如果大家写过后台管理系统的项目,那么动态路由一定是绕不开的,如果想偷懒的话,就把所有路由一开始都配置好,然后只根据后端返回的菜单列表渲染就好菜单就好了,但是这样的隐患就是我在地址栏输入的地址的时候,也会进入这个页面,不偷懒的方法就是本文要介绍

    2024年01月24日
    浏览(76)
  • vue3 element-plus动态菜单及动态图标

    引入element-plus 注册图标组件 动态引入图标代码 完整代码 路由如下

    2024年01月18日
    浏览(47)
  • 前端之vue 根据菜单自动生成路由(动态配置前端路由)

    在需要权限控制的页面,往往存在根据用户来显示菜单的情况,单独根据用户类型判断显然不是很好,如果后面用户类型发生变化,项目修改维护可能就会比较麻烦,所以比较好的做法是根据后端返回的菜单动态生成页面路由,以达到完全权限控制的目的,并且若权限发生变

    2024年04月10日
    浏览(42)
  • vue3使用Elementplus 动态显示菜单icon不生效

    菜单icon由后端提供,直接用的字符串返回,前端使用遍历显示,发现icon不会显示 后端提供的是字符串,那么在component :is=\\\"menu.icon\\\"/处读取到的也是字符串,而component组件中要求是一个能渲染的组件,类似如下结构: 想当然的,如果后端直接返回组件形式是不是就可以了。

    2024年02月11日
    浏览(41)
  • (二) Vue3 + Element-Plus 实现动态菜单栏

    系列介绍:Vue3 + Vite + TS 从零开始学习 项目搭建:(一) Vue3 + Vite + TS 项目搭建 实现动态菜单栏:(二) Vue3 + Element-Plus 实现动态菜单栏 实现动态面包屑:(三) Vue3 + Element-Plus 实现动态面包屑 实现动态标签页:(四) Vue3 + Element-Plus 实现动态标签页 实现动态主题色切换(demo):(五)

    2023年04月23日
    浏览(60)
  • vue2+antd——实现动态菜单路由功能——基础积累

    最近在写后台管理系统,遇到一个需求就是要将之前的静态路由改为动态路由,使用的后台框架是: vue-antd-admin 然后通过 loadRoutes 方法来实现异步动态路由。 如上图所示,需要在登录接口调用成功后,书写以下的代码: import { loadRoutes } from \\\'@/utils/routerUtil.js\\\'; import { getCodeL

    2024年02月08日
    浏览(41)
  • vue3.0+element Plus实现页面布局,侧边栏菜单路由跳转

    一. 先在router.js文件中配置路由,将侧边栏中需要跳转的页面都添加到children中 二. 在view目录下新建一个文件,里面包含侧边栏要跳转的页面 三.  页面样式布局 1. 我选择使用自定义组件BaseLayout.vue文件来设置header和aside样式显示 也可以使用element plus中的Container 布局容器 

    2024年02月13日
    浏览(51)
  • 补充 vue3用户管理权限(路由控制)

    之前有人问我 ,如果是二级路由如何添加,这里我做一个补充吧。直接拿方法去用就行。也不做解释了。稍微看下就能看懂了 假设,后端返回给我们一个数据 [“/defa”,\\\"/defa/defa1\\\"] 这样的一个路由表,我们就需要通过这个路由表去筛选匹配我们的动态路由,然后在进行添加。

    2024年01月21日
    浏览(48)
  • Vue3 + Element Plus 实现动态标签页及右键菜单

    目录 先上图  使用el-dropdown绑定右键菜单,为每个tab页绑定一个右键 右键菜单生效后控制每个下拉项的禁用与显示(每一项代表一个功能) 每个右键项对应的功能  控制每次只显示一个右键 完整代码         只有首页的情况         多个tab页的情况  

    2024年02月07日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包