数据库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