一、动态显示二级菜单

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

 
 
 

django中动态生成二级菜单的更多相关文章

  1. 应用rbac组件 动态生成一级菜单

    动态生成一级菜单 改表结构 需要知道是否是菜单\icon\名称权限表 +字段: is_menu = models.BooleanField(max_length=32,verbose_name='是否 ...

  2. JQuery实现动态生成树形菜单

    jQuery实现动态生成树形菜单 有一个需求:菜单导航条需要依据不同的权限动态提取出来.计划是将功能模块与用户权限之间的关系保持到一个配置表中.所以功能菜单的话就需要动态提取出来再显示.借助jquer ...

  3. jquery 根据后台传递过来的三维数组动态生成三级菜单

    根据后台传递过来的三维数组动态生成三级菜单 <!DOCTYPE html> <html lang="en"> <head> <meta c ...

  4. Celery 分布式任务队列快速入门 以及在Django中动态添加定时任务

    Celery 分布式任务队列快速入门 以及在Django中动态添加定时任务 转自 金角大王 http://www.cnblogs.com/alex3714/articles/6351797.html ...

  5. crm 动态一级二级菜单

    之前代码菜单是写是的 如何 让他 动态 生成了  首先 添加 2个字段 admin.py 更改 显示 from django.contrib import admin from rbac import ...

  6. 用C#从数据库动态生成AdminLTE菜单的一种方法

    当前的应用设计风格趋于Flat扁平化,很多基于BootStrap实现了很多UI非常漂亮的管理界面(Bootstrap admin template). 此核心文件开源在Github:https://g ...

  7. MVC5+EF6 入门完整教程13 -- 动态生成多级菜单

    稍微有一定复杂性的系统,多级菜单都是一个必备组件. 本篇专题讲述如何生成动态多级菜单的通用做法. 我们不用任何第三方的组件,完全自己构建灵活通用的多级菜单. 需要达成的效果:容易复用,可以根据mode ...

  8. EasyUI中动态生成标签页

    这是最近学到的内容,当时是有思路但是不知道怎么获取当前的点击对象,就没有实现功能,通过更深入的学习,我知道了不仅仅是Java,Oracle中有一个this,同样的EasyUI中也存在一个this,来获 ...

  9. django中怎样生成非HTML格式的内容。

    某些时候可能有这种需求.在网页中点击一个链接或者一个button希望返回一张图片.一个pdf文档.一个csv文档等而非HTML. 在diango中非常easy做到这些.django中的view用来接收 ...

随机推荐

  1. HDU-4676 Sum Of Gcd 莫队+欧拉函数

    题意:给定一个11~nn的全排列AA,若干个询问,每次询问给出一个区间[l,r][l,r],要求得出∑l≤i<j≤r  gcd(Ai,Aj)的值. 解法:这题似乎做的人不是很多,蒟蒻当然不会做只 ...

  2. HTML基础 img标签 做一个图库

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  3. Mysq修改引擎

    [数据库]Mysql更改默认引擎为Innodb的步骤方法   前言 InnoDB和MyISAM是许多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,视具体应用而定. 基本的差别为:MyI ...

  4. BZOJ4386 [POI2015]Wycieczki 矩阵+倍增

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4386 题解 一眼就可以看出来是邻接矩阵快速幂. 可是这里的边权不为 \(1\).不过可以发现, ...

  5. java 比较两个日期大小(2) 用before(), after()

    调试代码,我就不整理了,记下after()  before() 觉得这张图好美,从人家的博客上截的,找不到链接了

  6. 人生苦短_我用Python_pymysql库对Mysql数据库操作_009

    # coding=utf-8 import pymysql ''' 数据库的登录信息: config={ 'host':'118.126.108.xxx', # :主机 'user':'python' ...

  7. Linux用户登出之后保持后台进程(nohup)

    使用&可以将进程置于后台,但是用户从Shell登出之后,进程会自动结束.想要在登出之后保持进程运行,就要结合nohup命令使用. 例如: nohup find -size +100k > ...

  8. 【leetcode】883. Projection Area of 3D Shapes

    题目如下: 解题思路:分别求出所有立方体的个数,各行的最大值之和,各列的最大值之和.三者相加即为答案. 代码如下: class Solution(object): def projectionArea ...

  9. 4412 搭建tftp服务器

    搭建服务器 --安装xinetd,sudo apt-get install xinetd --安装tftp和tftpd,sudo apt-get install tftp tftpd --配置/etc ...

  10. SSH弱小算法支持问题

    SSH弱小算法支持问题:SSH的配置文件中加密算法没有指定(没有配置加密算法),则会默认支持所有加密算法,包括arcfour,arcfour128,arcfour256等弱加密算法.解决方法:1.修改 ...