根据权限动态生成二级菜单

数据库models设计:

from django.db import models

"""
一级菜单
"""
class Menu(models.Model):
    title = models.CharField(max_length=32, unique=True)
    icon = models.CharField(max_length=32, verbose_name="图标", null=True, blank=True)

    class Meta:
        verbose_name_plural = "菜单表"
        verbose_name = "菜单表"

    def __str__(self):
        return self.title

"""
有关联Menu表的是可以做二级展示菜单的权限
未关联Menu表的是不展示的权限
"""
class Permission(models.Model):
    """权限表"""
    titlt = models.CharField(max_length=32, verbose_name="功能")
    url = models.CharField(max_length=32, verbose_name="权限")
    menu = models.ForeignKey(to="Menu", null=True, blank=True)

    class Meta:
        verbose_name_plural = "权限表"
        verbose_name = "权限表"

    def __str__(self):
        return self.titlt

class Role(models.Model):
    """角色表"""
    name = models.CharField(max_length=32, verbose_name="角色名")
    permissions = models.ManyToManyField(to="Permission", verbose_name="角色所拥有的权限")

    class Meta:
        verbose_name_plural = "角色表"
        verbose_name = "角色表"

    def __str__(self):
        return self.name

class User(models.Model):
    """用户表"""
    name = models.CharField(max_length=32, verbose_name="用户名")
    password = models.CharField(max_length=32, verbose_name="密码")
    role = models.ManyToManyField(to="Role", verbose_name="用户拥有的角色")

    class Meta:
        verbose_name_plural = "用户表"
        verbose_name = "用户表"

    def __str__(self):
        return self.name


URL:

url(r‘^login/$‘, views.login),  

----------------------------------------------------------------------------

url判断要执行的函数

VIew登录函数:

from django.shortcuts import render, HttpResponse, redirect, reverse
from rbac import models
from django.conf import settings
from rbac.server.init_permission import init_permission

def login(request):
    if request.method == "POST":
        username = request.POST.get("username")
        pwd = request.POST.get("pwd")
        user = models.User.objects.filter(name=username, password=pwd).first()
        if not user:
            error_msg = "用户名或密码错误!"
            return render(request, "login.html", {"error_mag": error_msg})

        # 调用封装的函数
        init_permission(user, request)
        return redirect(reverse("customer"))
    return render(request, "login.html")

------------------------------------------------------------------------------------------------------------

用户在登录界面输入账号密码之后在login中获取并和数据库中的用户数据进行比对,如果取到了真实的用户, 则证明用户输入的账号密码正确, 调用封装好的函数进行设置session, 返回重定向到页面

封装好的设置session的函数:

"""
获取权限的函数
封装成组件
"""
from django.conf import settings

def init_permission(user, request):
    permission_list = user.role.filter(permissions__url__isnull=False).values(
        "permissions__url",
        "permissions__titlt",
        "permissions__menu__title",
        "permissions__menu__id",
        "permissions__menu__icon",
    ).distinct()
    # 存放权限信息的列表
    permission_li = []
    # 存放菜单信息的列表
    menu_li = {}
    # 单级菜单循环
    for i in permission_list:  # i 为字典形式
        permission_li.append({"url": i["permissions__url"]})
    #     if i.get("permissions__is_menu"):
    #         menu_li.append({"url": i["permissions__url"],
    #                         "icon": i["permissions__icon"],
    #                         "titlt": i["permissions__titlt"],
    #                         })
    # 二级菜单循环
        menu_id = i.get("permissions__menu__id")
        if not menu_id:
            continue
        if menu_id not in menu_li:
            menu_li[menu_id] = {
                "title": i["permissions__menu__title"],
                "icon": i["permissions__menu__icon"],
                "children": [
                    {"title": i["permissions__titlt"], "url": i["permissions__url"]}
                ]
            }
        else:
            menu_li[menu_id]["children"].append(
                {"title": i["permissions__titlt", "url": i["permissions__url"]]}
            )

    # 将权限信息写入session
    request.session[settings.PERMISSION_SESSION_KEY] = permission_li
    # 将菜单信息写入session
    request.session[settings.MENU_SESSION_KEY] = menu_li

---------------------------------------------------------------------------------------------------------------------

在数据库中取出需要的数据并去重, 二级菜单循环中获取menu_id是要判断Permission表是否有外键关联Menu表(即是否是二级展示的权限url)

获取session:

from django import template

register = template.Library()

from django.conf import settings
import re

"""
在此函数内获取init_permission初始化方法设置的session值
并且传递个menu.html进行渲染
"""
@register.inclusion_tag("menu.html")
def menu(request):
    menu_list = request.session.get(settings.MENU_SESSION_KEY)

    return {"menu_list": menu_list}

动态页面渲染:

<div class="multi-menu">
    {% for i in menu_list.values %}
        <div class="item">
            <div class="title"> <i class="fa {{ i.icon }}"></i> {{ i.title }}</div>
            <div class="body">
                {% for f in i.children %}
                    <a href="{{ f.url }}">{{ f.title }}</a>
                {% endfor %}
            </div>
        </div>
    {% endfor %}
</div>

中间件判断权限:

from django.utils.deprecation import MiddlewareMixin
from django.conf import settings
from django.shortcuts import render, HttpResponse, redirect, reverse
import re

class Permissionmiddleware(MiddlewareMixin):
    def process_request(self, request):
        # 目的 : 对权限进行校验
        # 获取当前访问的URL
        url = request.path_info
        # 判断访问的URL是否在白名单中
        for i in settings.WHITE_URL_LIST:
            if re.match(i, url):
                return

        # 获取用户所拥有的权限
        permission_list = request.session.get(settings.PERMISSION_SESSION_KEY)
        # 将获取的URL和获取的权限进行一致性校验
        for item in permission_list:
            url_p = item["url"]
            if re.match("^{}$".format(url_p), url):
                return
        else:
            return HttpResponse("没有权限!")

--------------------------------------------------------------------------------------------------------

在web初次发送请求时, 系统会在中间件中判断所请求时用的url是否在设置的白名单中, 如果在正常向下执行, 不在则获取用户的所拥有的权限,如果url在设置的白名单内, 执行白名单内的函数, 函数内会设置新的session, 当返回响应重定向时, 再次经过中间件, 则判断用户的权限(session和url的一致性校验)



根据权限动态生成二级菜单

原文地址:https://www.cnblogs.com/dong-/p/9880049.html

时间: 2024-10-29 05:10:14

根据权限动态生成二级菜单的相关文章

动态生成二级菜单

现在越来越多的用到二级甚至多级菜单,前台菜单的显示,手动指定也越来越不能满足要求,所以,动态生成菜单是必须的 思路 + 示例代码(以二级菜单为例) 先取出一级菜单内容值,接下来遍历一级菜单,将其id当做本次检索的parentid,将与之对应的二级菜单值获取到, 并加入到当前数组中(后台) 二层循环,当获取一个值时,检查其对于的二级菜单项是否有数据,有的话,则输出来,没有则跳过(前台) 以PHP后台为例 $res = mysql_query('*** where parentid = 0');  

动态生成多级菜单

MVC5+EF6 入门完整教程13 -- 动态生成多级菜单 稍微有一定复杂性的系统,多级菜单都是一个必备组件. 本篇专题讲述如何生成动态多级菜单的通用做法. 我们不用任何第三方的组件,完全自己构建灵活通用的多级菜单. 需要达成的效果:容易复用,可以根据model动态产生. 文章提纲 概述要点 && 理论基础 详细步骤 一.分析多级目录的html结构 二.根据html结构构建data model 三.根据data model动态生成树形结构 四.解析树形结构成html 总结 概述要点 &am

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

用C#从数据库动态生成AdminLTE菜单的一种方法 当前的应用设计风格趋于Flat扁平化,很多基于BootStrap实现了很多UI非常漂亮的管理界面(Bootstrap admin template). 此核心文件开源在Github:https://github.com/JackWangCUMT/AdminLTE-Menu-Generate.首先看一下主界面: 查看左边导航的菜单html结构(下面代码有错误,HTML自定义属性直接用空格进行分割,而不是,号进行分割,不然jquery获取定义属性

crm 动态一级二级菜单

之前代码菜单是写是的 如何 让他 动态 生成了  首先 添加 2个字段 admin.py 更改 显示 from django.contrib import admin from rbac import models # Register your models here. class PermissionAdmin(admin.ModelAdmin): list_display = ['url', 'title','is_menu','icon']#列表显示 list_editable = ['

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

稍微有一定复杂性的系统,多级菜单都是一个必备组件. 本篇专题讲述如何生成动态多级菜单的通用做法. 我们不用任何第三方的组件,完全自己构建灵活通用的多级菜单. 需要达成的效果:容易复用,可以根据model动态产生. 文章提纲 概述要点 && 理论基础 详细步骤 一.分析多级目录的html结构 二.根据html结构构建data model 三.根据data model动态生成树形结构 四.解析树形结构成html 总结 概述要点 && 理论基础 要实现动态菜单,只要解决两个问题:

WPF后台动态生成右键菜单

#region 循环生成右键菜单 private ContextMenu ContextMenus(Dictionary<string, RoutedEventHandler> list) { ContextMenu cm = new ContextMenu(); Style style = (Style)this.FindResource("ContextMenu"); //定义前台显示模板 cm.Style = style; foreach (var dc in lis

ASP.NET MVC动态生成网站菜单及子菜单

在开发ASP.NET MVC网站时,Insus.NET想实现动态产生网站的主菜单及子菜单. 你需要在网站管理后台管理此2张表(Menu,SubMenu)的信息,添加,删除,编辑,更新等. Sequence字段是序号.主菜单按此序号排序.IsMenu字段,添加上来的,不一定是菜单字段. 下面Insus.NET有此表添加的内容如下: 以上上主菜单,下面再来看来看看子菜单,结构与数据: 在子菜单的表结构中,也有一个Sequence字段,这个字段也是序号,不过它是按Controller字段来排序的.可以

c#从数据库读取数据动态生成树形菜单

页面: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebTree.aspx.cs" Inherits="Tree.WebTree" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/

生成树形菜单

题记------学习别人的精髓,并加以总结,消化吸收,这就是提高!!! 动态生成树形菜单,前台用easyui实现,非常简单不赘述,主要给出后台java的逻辑代码 1 package com.gongli.util.entity.treeMenu; 2 3 4 5 /* 6 * 用于封装树形菜单,无具体表与之对应,根节点为-1,节点0,然后父节点0,节点001,父节点001,节点001001,001002,001...依次类推 7 */ 8 public class TreeMenu { 9 pr