rbac组件之动态一级菜单栏实现
上一个版本,前端页面的左侧菜单栏在HTML中写死了,左侧菜单栏需要根据业务的不同而展示不同的菜单栏!!!
那么在当前的例子中,哪些可以成为菜单栏呢?
""" 客户管理 客户列表:/customer/list/ 添加客户:/customer/add/ 删除客户:/customer/list/(?P\d+)/ 修改客户:/customer/edit/(?P """ """ 客户列表和账单列表两个可以成为菜单 """\d+)/ 批量导入:/customer/import/ 下载模板:/customer/tpl/ 账单管理 账单列表:/payment/list/ 添加账单:/payment/add/ 删除账单:/payment/del/(?P \d+)/ 修改账单:/payment/edit/<?P \d+/
根据上一个版本的表结构也可以在所有URL中找出可以做菜单的URL,但是会很麻烦,那么此时可以在Permission权限表中,加入一个字段来标识来此URL是否可以做菜单
class Permission(models.Model): """权限表""" title = models.CharField( verbose_name="权限名称", max_length=32, ) url = models.CharField( verbose_name="含正则URL", max_length=128, ) is_menu = models.BooleanField( verbose_name="是否可以做菜单", default=False, ) icon = models.CharField( verbose_name="图标", max_length=64,
blank=True,
) def __str__(self): return self.title
菜单栏的图标,使用的是fontawesome,图标的形态不同,仅仅是class属性fa后面的代码不同,如:fa-address-book" aria-hidden="true">
权限初始化的时候,在session中再加入一条数据信息,即当前用户的菜单栏信息即可
from django.conf import settings def init_permission(current_user, request): permission_queryset = current_user.roles.filter( permissions__isnull=False, ).values( "permissions__id", "permissions__url", "permissions__title", "permissions__is_menu", "permissions__icon", ).distinct() permission_list = [] menu_list = [] for item in permission_queryset: permission_list.append(item["permissions__url"]) if item["permissions__is_menu"]: temp = { "url": item["permissions__url"], "title": item["permissions__title"], "icon": item["permissions__icon"], } menu_list.append(temp) request.session[settings.PERMISSION_SESSION_KEY] = permission_list request.session[settings.MENU_LIST] = menu_list """ permission_list = [ '/customer/list/', '/customer/add/', '/customer/list/(?P\\d+)/', '/customer/edit/(?P """\\d+)/', '/customer/import/', '/customer/tpl/', '/payment/list/', '/payment/add/', '/payment/del/(?P \\d+)/', '/payment/edit/<?P \\d+/' ] menu_list = [ {'url': '/customer/list/', 'title': '客户列表', 'icon': 'fa-address-book'}, {'url': '/payment/list/', 'title': '账单列表', 'icon': 'fa-money'} ]
此时,在session中存在两条数据信息,一条是权限,一条是菜单,权限已经完成了,当前问题是如何把菜单数据给渲染到前端页面呢?如果是在每一个需要用到菜单栏的HTML去编写代码,那么会很繁琐,虽然相同页面可以继承一个母版,但是不符合rbac组件的
编写原则,即拿即用。
那么可以将左侧菜单栏写成一个inclusion_tag,前端哪里需要直接调用即可,无需编写其余代码
rbac/templatetags/rbac.py
from django.template import Library from django.conf import settings import re register = Library() @register.inclusion_tag("rbac/menu.html") def menu(request): menu_list = request.session.get(settings.MENU_LIST) for item in menu_list: url = "^%s$" % item["url"] if re.match(url, request.path_info): item["class"] = "active" return {"menu_list": menu_list}
rbac/templates/rbac/menu.html
<div class="static-menu"> {% for menu in menu_list %} <a href="{{ menu.url }}" class="{{ menu.class }}"> <span class="icon-wrap"> <i class="fa {{ menu.icon }}">i> span> {{ menu.title }} a> {% endfor %} div>
前端调用
{# 指的是templatetags/rbac.py #}
{% load rbac %}
{# 需要用到一个参数request,所以调用时需要给其传参(inclusion_tag最多只能有两个参数) #}
{% menu request %}
rbac组件结构
总结:
""" 1 在Permission权限表加上is_menu字段,即可方便实现菜单栏的效果 2 在Permission权限表加上icon字段,方便菜单栏图标的渲染 3 在权限初始化中,根据is_menu的值(字段类型为布尔值)来判断是否可以做菜单,然后把可以做菜单的URL提取到另一个列表存储,该列表中数据是一个个字典,每个字典都有该菜单的URL、title、icon数据信息 4 为了前端的简单调用,rbac组件写了一个inclusion_tag,前端哪里需要直接调用该inclusion_tag即可 """
rbac动态一级菜单源码链接
链接:https://pan.baidu.com/s/11CNodIt3XE_LCPeTjB5pRw
提取码:abab