左侧菜单即权限管理

管理系统

左侧菜单:

表关系

 

 

数据库

class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=64)
    class Meta:
        verbose_name_plural = '用户表'
    def __str__(self):
        return self.username

#角色表
class Role(models.Model):
    caption = models.CharField(max_length=32)#角色
    class Meta:
        verbose_name_plural = '角色表'
    def __str__(self):
        return self.caption

#用户分配角色
class User2Role(models.Model):
    u = models.ForeignKey(User)#用户表
    r = models.ForeignKey(Role)#角色表
    class Meta:
        verbose_name_plural = '用户分配角色'
    def __str__(self):
        return "%s-%s" %(self.u.username,self.r.caption,)

#操作表
class Action(models.Model):
    # get  获取用户信息1
    # post  创建用户2
    # delete 删除用户3
    # put  修改用户4
    caption = models.CharField(max_length=32)#标题
    code = models.CharField(max_length=32)#操作

    class Meta:
        verbose_name_plural = '操作表'
    def __str__(self):
        return self.caption

#URL表
class Permission(models.Model):
    # http://127.0.0.1:8001/user.html  用户管理 1
    # http://127.0.0.1:8001/order.html 订单管理 1
    caption = models.CharField(max_length=32)#标题
    url = models.CharField(max_length=32)#链接
    menus=models.ForeignKey("Menus",null=True,blank=True)

    class Meta:
        verbose_name_plural = 'URL表'
    def __str__(self):
        return "%s-%s" %(self.caption,self.url,)

class Menus(models.Model):
    caption=models.CharField(max_length=32)
    parent_id=models.ForeignKey("self",null=True,blank=True)
    class Meta:
        db_table="Menus"
        verbose_name_plural="菜单表"
    def __str__(self):
        return self.caption

#权限表
class Permission2Action(models.Model):
    """
    1            1
    1            2
    1            3
    1            4
    2            2
    """
    p = models.ForeignKey(Permission)#url
    a = models.ForeignKey(Action)#增删改的请求
    class Meta:
        verbose_name_plural = '权限表'
    def __str__(self):
        return "%s-%s:-%s?t=%s" %(self.p.caption,self.a.caption,self.p.url,self.a.code,)

#角色分配权限
class Permission2Action2Role(models.Model):
    p2a = models.ForeignKey(Permission2Action)#权限表
    r = models.ForeignKey(Role)#用户
    class Meta:
        verbose_name_plural = '角色分配权限'
    def __str__(self):
        return "%s==>%s" %(self.r.caption,self.p2a,)

 

获取权限所需的值

            #获取当前用户的所有角色列表
            role_list=models.Role.objects.filter(user2role__u__username=self.username)

            #获取当前的权限列表{"p__url":url,"a__code":get}
            permission2action_list=models.Permission2Action.objects.filter(permission2action2role__r__in=role_list).values("p__url","a__code").distinct()

            permission2action_dict={}#转换成{"url":get}的格式
            for item in permission2action_list:
                if item["p__url"] in permission2action_dict:
                    permission2action_dict[item["p__url"]]=item["a__code"]
                else:
                    permission2action_dict[item["p__url"]]=["p__cole"]

            #获取菜单的叶子节点:即菜单的最后一层权限
            menu_leaf_list=list(models.Permission2Action.objects.filter(permission2action2role__r__in=role_list).exclude(p__menus__isnull=True).values("p_id","p__url","p__caption","p__menus").distinct())

            #获取所有的菜单列表
            menu_list=list(models.Menus.objects.values("id","caption","parent_id"))

生成菜单

          menu_leaf_dict={}
        open_leaf_parent_id=None

        #归并所有的叶子节点
        for item in self.menu_leaf_list:
            item = {
                'id': item['p_id'],
                'url': item['p__url'],
                'caption': item['p__caption'],
                'parent_id': item['p__menus'],
                'child': [],
                'status': True,  # 是否显示
                'open': False
            }
            #把列表变成字典,key是父级的id
            if item['parent_id'] in menu_leaf_dict:#把叶子节点同级的挂在一起,挂在父级id上
                menu_leaf_dict[item['parent_id']].append(item)
            else:
                menu_leaf_dict[item['parent_id']] = [item, ]

            if re.match(item['url'], self.current_url):#是否是链接的叶子节点
                item['open'] = True#有链接的叶子节点加一个状态等于True
                open_leaf_parent_id = item['parent_id']#重设标志位

        # 获取所有菜单字典
        menu_dict = {}
        for item in self.menu_list:
            #给每个菜单的字典设置初始状态
            item['child'] = []
            item['status'] = False
            item['open'] = False
            menu_dict[item['id']] = item#把列表变成字典key是自己的id

        # 讲叶子节点添加到菜单中
        for k, v in menu_leaf_dict.items():#循环最里层的叶子节点,key是父级的id
            menu_dict[k]['child'] = v#在菜单字典中id是叶子节点的id,所有在菜单字典中child里可以把最底层的叶子挂上去
            parent_id = k#k是叶子节点的父id,是菜单节点的id
            # 将后代中有叶子节点的菜单标记为【显示】通过while循环把一条线都标记
            while parent_id:
                menu_dict[parent_id]['status'] = True#第一次是叶子节点的父id,当前菜单的id,在菜单把status的状态改成True
                parent_id = menu_dict[parent_id]['parent_id']#把当前的菜单的父id找到并赋值,每次就找到的父亲

        # 将已经选中的菜单标记为【展开】
        while open_leaf_parent_id:#等于True表示菜单中有链接,当前连接的一条线标记为True
            menu_dict[open_leaf_parent_id]['open'] = True
            open_leaf_parent_id = menu_dict[open_leaf_parent_id]['parent_id']

        # 生成树形结构数据
        result = []#用来放菜单根的
        for row in menu_dict.values():#循环菜单字典
            if not row['parent_id']:#判断是否是根
                result.append(row)
            else:
                menu_dict[row['parent_id']]['child'].append(row)#row['parent_id']是父id,
                # 把当前菜单挂在父id的child列表里
    #result是最后的结果

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    {% block css %}
    <style>
        .content{
            margin-left: 20px;
        }
        .content a{
            display: block;
        }
        .active{
            color: red;
        }
        .content .title,a{
{#            display: none;#}
        }
        .hide{
            display: none;
        }



    </style>
    {% endblock %}
</head>
<body>
{% block content %}
    <div style="float: left;width: 20%">
        {{ menu_string |safe }}
    </div>
    <div style="float: left;width: 80%">
        {% if "get" in action_list %}
            <a href="http://www.baidu.com">添加</a>
        {% endif %}

    </div>



{% endblock %}
<script src="/static/js/jquery-3.1.1.js"></script>
<script>

</script>
</body>
</html>

 

封装到类里面

左侧菜单简单版

from django.shortcuts import render,HttpResponse

# Create your views here.
from app01 import models


class MenuHelper(object):
    def __init__(self,id,current_url):
        self.permission2action_list=None
        self.result=None
        self.id=id
        self.current_url=current_url

        self.init_data()

    def init_data(self):

        role_list=models.Role.objects.filter(user2role__u__id=self.id)
        permission2action_list=models.Permission2Action.objects.filter(permission2action2role__r__in=role_list).values("p__url","a__code").distinct()
        self.permission2action_list=permission2action_list
        #这个人所得到的权限,可保存在session
                                                                    #所有角色在不在这个人的角色里             #必须是要和菜单有关联的不能是空的
        menu_leaf_list=models.Permission2Action.objects.filter(permission2action2role__r__in=role_list).exclude(p__menus__isnull=True).values("p_id","p__url","p__caption","p__menus").distinct()
        #取到的是最底成的链接

        menu_leaf_dic={}
        open_leaf_parent_id=None
        for item in menu_leaf_list:
            item={
                "id":item["p_id"],
                "url":item["p__url"],
                "caption":item["p__caption"],
                "parent_id":item["p__menus"],
                "child":[],
                "status":True,
                "open":False
            }
            #取出最底层的链接转换成字典
            if item["parent_id"]in menu_leaf_dic:
                menu_leaf_dic[item["parent_id"]].append(item)
            else:
                menu_leaf_dic[item["parent_id"]]=[item,]
            #把链接上做一个挂在菜单上的钩子
            import re
            if re.match(item["url"],self.current_url):
                item["open"]=True#有链接就改变状态
                open_leaf_parent_id=item["parent_id"]

        menu_list=models.Menus.objects.values('id', 'caption', 'parent_id')
        menu_dict={}
        for item in menu_list:
            item["child"]=[]
            item["status"]=False
            item["open"]=False
            menu_dict[item["id"]]=item
        #取出所有放到字典里

        for k,v in menu_leaf_dic.items():
            menu_dict[k]["child"]=v#把链接放到菜单上了
            parent_id=k
            while parent_id:
                #把有东西的菜单的状态变成True
                menu_dict[parent_id]["status"]=True
                parent_id=menu_dict[parent_id]["parent_id"]
        while open_leaf_parent_id:
            #把需要展开的菜单的状态改变为True
            menu_dict[open_leaf_parent_id]["open"]=True
            open_leaf_parent_id=menu_dict[open_leaf_parent_id]["parent_id"]

        result=[]
        for item in menu_dict.values():

            if not item["parent_id"]:
                result.append(item)
            else:
                menu_dict[item["parent_id"]]["child"].append(item)
        self.result=result

    def menu_content(self,child_list):
        response=""
        tpl="""
            <div class="item %s">
                <div class="title">%s</div>
                <div class="content">%s</div>
            </div>
        """
        for item in child_list:
            if not item["status"]:
                continue
            hide=""
            if item["open"]:
                hide="hide"
            if "url"in item:
                response += "<a class='%s' href='%s'>%s</a>" % (hide, item['url'], item['caption'])
            else:
                title=item["caption"]
                content=self.menu_content(item["child"])
                response+=tpl%(hide,title,content)
        return response

    def menu_tree(self):
        response=""
        tpl="""
            <div class="item %s">
                <div class="title">%s</div>
                <div class="content">%s</div>
            </div>

        """
        for item in self.result:
            if not item["status"]:
                continue
            hide=""
            if item["open"]:
                hide="hide"
            title=item["caption"]
            content=self.menu_content(item["child"])
            response+=tpl%(hide,title,content)
        return response


def login(request):
    # user_request_url = "/product.html"
    user_request_url = "/order.html"
    # user_request_url = "/girl.html"
    id=6
    obj = MenuHelper(id, user_request_url)
    string = obj.menu_tree()
    return render(request,"index3.html",{"menu_string":string})
左侧菜单

 

加上权限的左侧菜单

牛逼版

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
from app01 import models
import re


class MenuHelper(object):
    def __init__(self,request,username):
        self.request=request    #当前请求的request对象
        self.username=username  #当前用户
        self.current_url=request.path_info  #当前url

        self.permission2action_dict=None    #当前用户所有权限
        self.menu_leaf_list=None    #当前菜单中显示的权限
        self.menu_list=None #当前所有菜单

        self.session_data()

    def session_data(self):
        permission_dict=self.request.session.get("permission_info")
        if permission_dict:
            self.permission2action_dict=permission_dict["permission2action_dict"]
            self.menu_leaf_list=permission_dict["menu_leaf_list"]
            self.menu_list=permission_dict["menu_list"]
        else:
            #获取当前用户的所有角色列表
            role_list=models.Role.objects.filter(user2role__u__username=self.username)

            #获取当前的权限列表{"p__url":url,"a__code":get}
            permission2action_list=models.Permission2Action.objects.filter(permission2action2role__r__in=role_list).values("p__url","a__code").distinct()

            permission2action_dict={}#转换成{"url":get}的格式
            for item in permission2action_list:
                if item["p__url"] in permission2action_dict:
                    permission2action_dict[item["p__url"]]=item["a__code"]
                else:
                    permission2action_dict[item["p__url"]]=["p__cole"]

            #获取菜单的叶子节点:即菜单的最后一层权限
            menu_leaf_list=list(models.Permission2Action.objects.filter(permission2action2role__r__in=role_list).exclude(p__menus__isnull=True).values("p_id","p__url","p__caption","p__menus").distinct())

            #获取所有的菜单列表
            menu_list=list(models.Menus.objects.values("id","caption","parent_id"))

            self.request.session["permission_info"]={
                "permission2action_dict":permission2action_dict,
                "menu_leaf_list":menu_leaf_list,
                "menu_list":menu_list
            }   #放到session里

            self.permission2action_dict=permission2action_dict
            self.menu_leaf_list=menu_leaf_list
            self.menu_list=menu_list

    def menu_data_list(self):
        menu_leaf_dict={}
        open_leaf_parent_id=None

        #归并所有的叶子节点
        for item in self.menu_leaf_list:
            item = {
                'id': item['p_id'],
                'url': item['p__url'],
                'caption': item['p__caption'],
                'parent_id': item['p__menus'],
                'child': [],
                'status': True,  # 是否显示
                'open': False
            }
            #把列表变成字典,key是父级的id
            if item['parent_id'] in menu_leaf_dict:#把叶子节点同级的挂在一起,挂在父级id上
                menu_leaf_dict[item['parent_id']].append(item)
            else:
                menu_leaf_dict[item['parent_id']] = [item, ]

            if re.match(item['url'], self.current_url):#是否是链接的叶子节点
                item['open'] = True#有链接的叶子节点加一个状态等于True
                open_leaf_parent_id = item['parent_id']#重设标志位

        # 获取所有菜单字典
        menu_dict = {}
        for item in self.menu_list:
            #给每个菜单的字典设置初始状态
            item['child'] = []
            item['status'] = False
            item['open'] = False
            menu_dict[item['id']] = item#把列表变成字典key是自己的id

        # 讲叶子节点添加到菜单中
        for k, v in menu_leaf_dict.items():#循环最里层的叶子节点,key是父级的id
            menu_dict[k]['child'] = v#在菜单字典中id是叶子节点的id,所有在菜单字典中child里可以把最底层的叶子挂上去
            parent_id = k#k是叶子节点的父id,是菜单节点的id
            # 将后代中有叶子节点的菜单标记为【显示】通过while循环把一条线都标记
            while parent_id:
                menu_dict[parent_id]['status'] = True#第一次是叶子节点的父id,当前菜单的id,在菜单把status的状态改成True
                parent_id = menu_dict[parent_id]['parent_id']#把当前的菜单的父id找到并赋值,每次就找到的父亲

        # 将已经选中的菜单标记为【展开】
        while open_leaf_parent_id:#等于True表示菜单中有链接,当前连接的一条线标记为True
            menu_dict[open_leaf_parent_id]['open'] = True
            open_leaf_parent_id = menu_dict[open_leaf_parent_id]['parent_id']

        # 生成树形结构数据
        result = []#用来放菜单根的
        for row in menu_dict.values():#循环菜单字典
            if not row['parent_id']:#判断是否是根
                result.append(row)
            else:
                menu_dict[row['parent_id']]['child'].append(row)#row['parent_id']是父id,
                # 把当前菜单挂在父id的child列表里

        return result#成型的大树

    def menu_content(self,child_list):
        response=""
        tpl="""
            <div class="item %s">
                <div class="title">%s</div>
                <div class="content">%s</div>
            </div>
        """
        for item in child_list:
            if not item["status"]:
                continue
            hide=""
            if item["open"]:
                hide="hide"
            if "url"in item:
                response += "<a class='%s' href='%s'>%s</a>" % (hide, item['url'], item['caption'])
            else:
                title=item["caption"]
                content=self.menu_content(item["child"])
                response+=tpl%(hide,title,content)
        return response

    def menu_tree(self):
        response=""
        tpl="""
            <div class="item %s">
                <div class="title">%s</div>
                <div class="content">%s</div>
            </div>

        """
        for item in self.menu_data_list():
            if not item["status"]:
                continue
            hide=""
            if item["open"]:
                hide="hide"
            title=item["caption"]
            content=self.menu_content(item["child"])
            response+=tpl%(hide,title,content)
        return response

    def actions(self):
        """
        检查用户是否对当前URL有访问权,并获取对当前URL有什么权限
        :param request:
        :return:
        """
        url_regex=None
        action_list=[]
        #当前所有权限
        for k,v in self.permission2action_dict.items():
            if re.match(k,self.current_url):
                url_regex=k
                action_list=v
                break
        return action_list

def logout(request):
    """
    清空session的函数
    :param request:
    :return:
    """
    request.session.clear()
    return redirect("/login.html")

def login(request):
    """
    登录验证
    :param request:
    :return:
    """
    if request.method=="GET":
        return render(request,"login.html")
    else:
        username=request.POST.get("username")
        pwd = request.POST.get("pwd")
        obj=models.User.objects.filter(username=username,password=pwd).first()
        if obj:#如果有这个用户则把用户加到session里,并实例化MenuHelper类
            request.session["user_info"]={"nid":obj.id,"username":obj.username}

            MenuHelper(request,obj.username)
            return redirect("/index.html")

        else:
            return redirect("/login.html")

def permission(func):#func=被装饰的函数
    def inner(request,*args,**kwargs):#被装饰的函数执行时才执行inner
        user_info = request.session.get("user_info")#在session中取用户
        if not user_info:#没取到则返回登陆页面
            return redirect("/login.html")
        obj = MenuHelper(request, user_info["username"])#在session中取到则实例化MenuHelper类
        action_list = obj.actions()#判断当前用户有哪些当前url的权限
        if not action_list:#为空则是没权限
            return HttpResponse("无权限访问")
        menu_string = obj.menu_tree()#把html数据取出来
        kwargs["menu_string"]=menu_string#当成参数传到被装饰的函数
        kwargs["action_list"]=action_list#当成参数传到被装饰的函数
        return func(request,*args,**kwargs)#真正执行被装饰的函数的地方
    return inner#被装饰的函数被inner代替了

@permission  # index=permission(index)
def index(request,*args,**kwargs):#kwargs是装饰器传的参数
    menu_string=kwargs.get("menu_string")
    action_list=kwargs.get("action_list")
    if "GET" in action_list:#判断有没有看的权限
        result=models.User.objects.all()
    else:
        result=[]

    return render(request,"index.html",{"menu_string":menu_string,"action_list":action_list})
View Code

 

posted @ 2017-04-12 15:11  陨落&新生  阅读(557)  评论(0编辑  收藏  举报