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查询的方便,为开发造成了困难,所以不推荐这样做!

      

     
     
     
  • 相关阅读:
    java基础部分的一些有意思的东西。
    antdvue按需加载插件babelpluginimport报错
    阿超的烦恼 javaScript篇
    .NET E F(Entity Framework)框架 DataBase First 和 Code First 简单用法。
    JQuery获得input ID相同但是type不同的方法
    gridview的删除,修改,数据绑定处理
    jgGrid数据格式
    Cannot read configuration file due to insufficient permissions
    Invoke action which type of result is JsonResult on controller from view using Ajax or geJSon
    Entity model数据库连接
  • 原文地址:https://www.cnblogs.com/baby12138/p/10834088.html
Copyright © 2011-2022 走看看