修改表结构
rbac/models.py
from django.db import models
class Menu(models.Model):
"""
菜单表
"""
title = models.CharField(verbose_name='一级菜单名称', max_length=32)
icon = models.CharField(verbose_name='图标', max_length=32, null=True, blank=True)
def __str__(self):
return self.title
class Permission(models.Model):
"""
权限表
"""
title = models.CharField(verbose_name='标题', max_length=32)
url = models.CharField(verbose_name='含正则的URL', max_length=128)
name = models.CharField(verbose_name='URL别名', max_length=32, null=True, unique=True)
menu = models.ForeignKey(verbose_name='所属菜单', to='Menu', null=True, blank=True, help_text='null表示不是菜单;非null表示是二级菜单',on_delete=models.CASCADE)
pid = models.ForeignKey(verbose_name='关联的权限', to='Permission', null=True, blank=True,related_name='parents',
help_text='对于非菜单权限需要选择一个可以成为菜单的权限,用户做默认展开和选中菜单',on_delete=models.CASCADE)
def __str__(self):
return self.title
class Role(models.Model):
"""
角色
"""
title = models.CharField(verbose_name='角色名称', max_length=32)
permissions = models.ManyToManyField(verbose_name='拥有的所有权限', to='Permission', blank=True)
def __str__(self):
return self.title
class UserInfo(models.Model):
"""
用户表
"""
name = models.CharField(verbose_name='用户名', max_length=32)
password = models.CharField(verbose_name='密码', max_length=64)
email = models.CharField(verbose_name='邮箱', max_length=32)
roles = models.ManyToManyField(verbose_name='拥有的所有角色', to='Role', blank=True)
def __str__(self):
return self.name
表创建好之后新增字段值
权限初始化代码优化,将菜单权限返回制作成字典
rbac/service/init_Permission.py
# -*- encoding: utf-8 -*-
"""
@File : init_Permission.py
@Time : 2021-12-16 22:30
@Author : tangsai
@Email : 294168604@qq.com
@Software: PyCharm
"""
from django.conf import settings
def init_Permission(current_user, request):
"""
用户权限的初始化
:param current_user: 当前用户对象
:param request: 请求相关所有数据
:return:
"""
# 2. 权限信息初始化
# 根据当前用户信息获取此用户所拥有的所有权限,并放入session。
# 当前用户所有权限
permission_queryset = current_user.roles.filter(permissions__isnull=False).values("permissions__id",
"permissions__title",
"permissions__url",
"permissions__name",
"permissions__pid_id",
"permissions__pid__title",
"permissions__pid__url",
"permissions__menu_id",
"permissions__menu__title",
"permissions__menu__icon"
).distinct()
# 3. 获取权限+菜单信息
permission_dict = {}
menu_dict = {}
for item in permission_queryset:
permission_dict[item['permissions__name']] = {
'id': item['permissions__id'],
'title': item['permissions__title'],
'url': item['permissions__url'],
'pid': item['permissions__pid_id'],
'p_title': item['permissions__pid__title'],
'p_url': item['permissions__pid__url'],
}
menu_id = item['permissions__menu_id']
if not menu_id:
continue
node = {'id': item['permissions__id'], 'title': item['permissions__title'], 'url': item['permissions__url']}
if menu_id in menu_dict:
menu_dict[menu_id]['children'].append(node)
else:
menu_dict[menu_id] = {
'title': item['permissions__menu__title'],
'icon': item['permissions__menu__icon'],
'children': [node, ]
}
request.session[settings.PERMISSION_SESSION_KEY] = permission_dict
request.session[settings.MENU_SESSION_KEY] = menu_dict
中间件代码修改,session返回是个字典需要兼容
rbac/middlewares/rbac.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
from django.conf import settings
class RbacMiddleware(MiddlewareMixin):
"""
用户权限信息校验
"""
def process_request(self, request):
"""
当用户请求刚进入时候出发执行
:param request:
:return:
"""
"""
1. 获取当前用户请求的URL
2. 获取当前用户在session中保存的权限列表 ['/customer/list/','/customer/list/(?P<cid>\\d+)/']
3. 权限信息匹配
"""
current_url = request.path_info
for valid_url in settings.VALID_URL_LIST:
if re.match(valid_url, current_url):
# 白名单中的URL无需权限验证即可访问
return None
permission_dict = request.session.get(settings.PERMISSION_SESSION_KEY)
if not permission_dict:
return HttpResponse('未获取到用户权限信息,请登录!')
flag = False
url_record = [
{'title': '首页', 'url': '#'}
]
for item in permission_dict.values():
reg = "^%s$" % item['url']
if re.match(reg, current_url):
flag = True
request.current_selected_permission = item['pid'] or item['id']
if not item['pid']:
url_record.extend([{'title': item['title'], 'url': item['url'], 'class': 'active'}])
else:
url_record.extend([
{'title': item['p_title'], 'url': item['p_url']},
{'title': item['title'], 'url': item['url'], 'class': 'active'},
])
request.breadcrumb = url_record
print(request.breadcrumb)
break
if not flag:
return HttpResponse('无权访问')
inclond_tag模板代码修改
rbac/templatetags/rbac.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django.template import Library
from django.conf import settings
from collections import OrderedDict
import re
register = Library()
@register.inclusion_tag('rbac/static_menu.html')
def static_menu(request):
"""
创建一级菜单
:return:
"""
menu_list = request.session[settings.MENU_SESSION_KEY]
return {'menu_list': menu_list}
@register.inclusion_tag('rbac/multi_menu.html')
def multi_menu(request):
"""
创建二级菜单
:return:
"""
menu_dict = request.session[settings.MENU_SESSION_KEY]
# 对字典的key进行排序
key_list = sorted(menu_dict)
# 空的有序字典
ordered_dict = OrderedDict()
for key in key_list:
val = menu_dict[key]
val['class'] = 'hide'
for per in val['children']:
if per['id'] == request.current_selected_permission:
per['class'] = 'active'
val['class'] = ''
ordered_dict[key] = val
return {'menu_dict': ordered_dict}
@register.inclusion_tag('rbac/breadcrumb.html')
def breadcrumb(request):
return {'record_list': request.breadcrumb}
@register.filter
def has_permission(request, name):
"""
判断是否有权限
:param request:
:param name:
:return:
"""
if name in request.session[settings.PERMISSION_SESSION_KEY]:
return True
模板修改:
customer_list.html
{% extends 'layout.html' %}
{% load rbac %}
{% block content %}
<div class="luffy-container">
<div class="btn-group" style="margin: 5px 0">
{% if request|has_permission:"customer_add" %}
<a class="btn btn-default" href="/customer/add/">
<i class="fa fa-plus-square" aria-hidden="true"></i> 添加客户
</a>
{% endif %}
{% if request|has_permission:"customer_import" %}
<a class="btn btn-default" href="/customer/import/">
<i class="fa fa-file-excel-o" aria-hidden="true"></i> 批量导入
</a>
{% endif %}
</div>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>ID</th>
<th>客户姓名</th>
<th>年龄</th>
<th>邮箱</th>
<th>公司</th>
{% if request|has_permission:"customer_del" or request|has_permission:"customer_edit" %}
<th>选项</th>
{% endif %}
</tr>
</thead>
<tbody>
{% for row in data_list %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.name }}</td>
<td>{{ row.age }}</td>
<td>{{ row.email }}</td>
<td>{{ row.company }}</td>
{% if request|has_permission:"customer_del" or request|has_permission:"customer_edit" %}
<td>
{% if request|has_permission:"customer_edit" %}
<a style="color: #333333;" href="/customer/edit/{{ row.id }}/">
<i class="fa fa-edit" aria-hidden="true"></i></a>
{% endif %}
{% if request|has_permission:"customer_del" %}
<a style="color: #d9534f;" href="/customer/del/{{ row.id }}/"><i
class="fa fa-trash-o"></i></a>
{% endif %}
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
payment_list.html
{% extends 'layout.html' %}
{% load rbac %}
{% block content %}
<div class="luffy-container">
{% if request|has_permission:"payment_add" %}
<div style="margin: 5px 0;">
<a class="btn btn-success" href="/payment/add/">
<i class="fa fa-plus-square" aria-hidden="true"></i> 添加缴费记录
</a>
</div>
{% endif %}
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>ID</th>
<th>客户姓名</th>
<th>金额</th>
<th>付费时间</th>
{% if request|has_permission:"payment_del" or request|has_permission:"payment_edit" %}
<th>选项</th>
{% endif %}
</tr>
</thead>
<tbody>
{% for row in data_list %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.customer.name }}</td>
<td>{{ row.money }}</td>
<td>{{ row.create_time|date:"Y-m-d H:i:s" }}</td>
{% if request|has_permission:"payment_del" or request|has_permission:"payment_edit" %}
<td>
{% if request|has_permission:"payment_edit" %}
<a style="color: #333333;" href="/payment/edit/{{ row.id }}/">
<i class="fa fa-edit" aria-hidden="true"></i></a>
{% endif %}
{% if request|has_permission:"payment_del" %}
<a style="color: #d9534f;" href="/payment/del/{{ row.id }}/"><i
class="fa fa-trash-o"></i></a>
{% endif %}
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}