zoukankan      html  css  js  c++  java
  • Django

    一、动态显示二级菜单

      上篇随笔中,我们实现了动态显示一级菜单,现在考虑这样一种情况,用户的菜单权限比较多,这个时候全部并列展现在左侧菜单就不合适了,所以,现在有这样一个需求,即把用户的菜单权限分类,划分成二级菜单,动态显示在左侧菜单,解决方案如下:

    1、修改权限表结构

      (1)分析需求,要求左侧菜单如下显示:

        客户管理:

          客户列表

        账单管理:

          账单列表

      (2)修改rbac下的models.py,修改后代码如下:

    from django.db import models
    
    class User(models.Model):
        """
        用户表
        """
        name = models.CharField(verbose_name='用户名', max_length=32)
        password = models.CharField(verbose_name='密码', max_length=32)
        roles = models.ManyToManyField(verbose_name='拥有的所有角色', to='Role')
        def __str__(self):
            return self.name
    
    class Role(models.Model):
        """
        角色表
        """
        title = models.CharField(verbose_name='角色名称', max_length=32)
        permissions = models.ManyToManyField(verbose_name='拥有的所有权限', to='Permission')
        def __str__(self):
            return self.title
    
    class Permission(models.Model): # 建立与菜单类的关联,去掉is_menu和icon
        """
        权限表
        """
        url = models.CharField(verbose_name='含正则的URL', max_length=32)
        title = models.CharField(verbose_name='标题', max_length=32)
        menu = models.ForeignKey(verbose_name='所属菜单', to="Menu", on_delete=models.CASCADE, null=True)
        def __str__(self):
            return self.title
    
    
    class Menu(models.Model):   # 新增一个菜单表
        title = models.CharField(max_length=32, verbose_name='菜单')
        icon = models.CharField(max_length=32, verbose_name='图标', null=True, blank=True)

    2、注入session(重点是构建数据结构),setsession.py中代码修改如下:

    def initial_session(user_obj, request):
        """
        将当前登录人的所有权限url列表和自己构建的所有菜单权限字典注入session
        :param user_obj: 当前登录用户对象
        :param request: 请求对象HttpRequest
        """
        # 查询当前登录人的所有权限列表
        ret = Role.objects.filter(user=user_obj).values('permissions__url',
                                                        'permissions__title',
                                                'permissions__menu__title',
                                                        'permissions__menu__icon',
                                                        'permissions__menu__id').distinct()
        permission_list = []
        permission_menu_dict = {}
        for item in ret:
            # 获取用户权限列表用于中间件中权限校验
            permission_list.append(item['permissions__url'])
            menu_pk = item['permissions__menu__id']
            if menu_pk:
                if menu_pk not in permission_menu_dict:
                    permission_menu_dict[menu_pk] = {
                        "menu_title": item["permissions__menu__title"],
                        "menu_icon": item["permissions__menu__icon"],
                        "children": [
                            {
                                "title": item["permissions__title"],
                                "url": item["permissions__url"],
                            }
                        ],
                    }
                else:
                    permission_menu_dict[menu_pk]["children"].append({
                        "title": item["permissions__title"],
                        "url": item["permissions__url"],
                    })
        print('权限列表', permission_list)
        print('菜单权限', permission_menu_dict)
        # 将当前登录人的权限列表注入session中
        request.session['permission_list'] = permission_list
        # 将当前登录人的菜单权限字典注入session中
        request.session['permission_menu_dict'] = permission_menu_dict

    3、从session中取出菜单权限信息,修改my_tags.py文件,代码如下:

    from django.template import Library
    register =Library()
    
    @register.inclusion_tag("menu.html")
    def get_menu_styles(request):
        permission_menu_dict = request.session.get("permission_menu_dict")
        return {"permission_menu_dict": permission_menu_dict}

    4、渲染页面,修改menu.html文件,代码如下:

    <div class="multi-menu">
        {% for item in permission_menu_dict.values %}
            <div class="item">
                <div class="title">
                    <i class="{{ item.menu_icon }}"></i>{{ item.menu_title }}
                </div>
                <div class="body">
                    {% for foo in item.children %}
                        <a href="{{ foo.url }}">{{ foo.title }}</a>
                    {% endfor %}
                </div>
            </div>
        {% endfor %}
    </div>

    到此,二级菜单已经渲染到页面中了,样式或者其他js效果就靠你的前端技术了!

    二、补充知识点

    1、DATABASES的使用

      我们知道django项目使用数据库要在settings.py中通过设置DATABASES给项目配置数据库引擎,我们之前都是给项目设置成MySQL或者django默认的sqlite3数据库,大家知道一个项目可以有多个应用,并且事实也是如此的,每个项目下也会自己的模型类,按照之前的做法,在定义了数据库引擎之后做数据库迁移,那么每个app下的数据库都使用settings中指定的数据库了,但是你可能会有这样的需求,就是不同的应用使用不同的数据库,该如何做呢?没错,也是设置DATABASES,方式如下:

    DATABASES = {
        'default': {   # 下面没有指定的都使用default下的数据库引擎
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        },
        'app01':{    # app01使用mysql数据库引擎
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'bms',   # 要连接的数据库,连接前需要创建好
            'USER': 'root',  # 连接数据库的用户名
            'PASSWORD': '',  # 连接数据库的密码
            'HOST': '127.0.0.1',  # 连接主机,默认本机
            'PORT': 3306   #  端口 默认3306
        }
    }

    2、ForeignKey的参数db_constraint解释

      在学习数据库时,我们通过定义外键使两个表建立连接和约束,但有时我们需要只建立连接,不建立约束,也就是通过在表中建立另一个表的id,不设置foreignkey约束。

      Django的ForeignKey也为我们想好了这两种情况:

        (1)db_constraint = True 表示两个表之间既建立了连接又有约束,并支持ORM语法查询;

        (2)db_constraint = False 表示两个表之间只建立了连接,没有建立约束,并支持ORM语法查询;

      注意:当然你可能会想到能否将ForeignKey改为一个IntegerField,通过定义IntegerField字段的值来与另一个表建立联系,这种方法也没错,但是这样就不能使用ORM语法查询,也就享受不到ORM查询的方便,为开发造成了困难,所以不推荐这样做!

  • 相关阅读:
    Linux高并发内核优化-TougheRadius
    Zabbix 4.0 配置邮件报警功能
    Zabbix Agent 4.0 Windows 安装配置
    zabbix4.0前端个性化设置
    zabbix 4.0中文图形界面乱码问题
    Zabbix4.0系统告警“More than 75% used in the configuration cache”
    Zabbix4.0配置SNMP监控
    Zabbix4.0 SNMP安装
    Zabbix4.0添加cisco交换机基本监控步骤
    深入.NET框架
  • 原文地址:https://www.cnblogs.com/wxj1129549016/p/9993445.html
Copyright © 2011-2022 走看看