1.批量操作权限
1.定义一个可以拿到所有路由的函数的py文件,建议放在权限目录下
代码语言:javascript
复制from collections import OrderedDict
from django.conf import settings
from django.urls import RegexURLResolver
from django.utils.module_loading import import_string
def recursion_urls(pre_namespace, pre_url, url_patterns, url_ordered_dict):
"""
递归解析所有的 include ,得到所有的 url
:return:
"""
# 循环 include 的url列表
for item in url_patterns: # 值循環一次的
if isinstance(item, RegexURLResolver): # 这一段代码的作用就是为了将所有的 include 转换为 非include
# 如果有 namespace
if pre_namespace:
if item.namespace:
# 那就拼接
namespace = '{}:{}'.format(pre_namespace, item.namespace)
else:
namespace = item.namespace
else:
if item.namespace:
namespace = item.namespace
else:
namespace = None
"""
print(pre_url item.regex.pattern) '/' '^old'/ --> /^old/,拼接过后的新的url前缀
print(item.url_patterns) ---> include url下面的其余的 url 列表
"""
# 递归,只有在 include 的url才递归
recursion_urls(namespace, pre_url item.regex.pattern, item.url_patterns, url_ordered_dict)
# 如果已经不是include的url
else:
if pre_namespace:
name = '{}:{}'.format(pre_namespace, item.name)
else:
name = item.name
if not item.name:
raise Exception('URL路由里面必须有name属性')
# print('name--->', name) # web:payment_list
# print('item2--->', item._regex) # payment/list/$
url = pre_url item._regex
# print('url--->', url) # /^old/payment/list/$
url_ordered_dict[name] = {'name': name, 'URL': url.replace('^', '').replace('$', '')}
print(url_ordered_dict)
return url_ordered_dict
def get_all_routes_url(ignore_namespace_list=None):
"""
从路由里面获取所有的 url
:return:
"""
# 将被忽略的url列表
ignore_list = ignore_namespace_list or []
# 定义一个有序字典,存放 url
url_ordered_dict = OrderedDict()
# 拿到项目根目录的 url.py 这个模块,相当于变相导入
md = import_string(settings.ROOT_URLCONF)
# 定义列表存放 include 的url
include_urlpatterns = []
# 循环 urls 里面的 url对象 列表
for item in md.urlpatterns:
# print('哈哈哈{}'.format(item.namespace), item.url_patterns)
# print('n')
# 如果这是一个 include 的url对象并且它的 namespace 是被忽略的
if isinstance(item, RegexURLResolver) and item.namespace in ignore_list:
continue
include_urlpatterns.append(item)
"""
走到这一步就是可以直接全部筛选出所有的符合条件的根 include url
"""
# print('根部 url 列表', include_urlpatterns)
recursion_urls(None, '/', include_urlpatterns, url_ordered_dict)
return url_ordered_dict
# print('url_ordered_dict', url_ordered_dict)
2.在views中,导入上面的方法使用
代码语言:javascript
复制# 批量操作权限
def multi_permission(request):
# 你要做什么
action_type = request.GET.get('type')
print(action_type)
# 接收类表和类表Form
FormSet = modelformset_factory(models.Permission, forms.MultiPermission, extra=0)
# 新增用的权限
AddFormSet = formset_factory(forms.MultiPermission, extra=0)
# 取出数据库里面的所有的权限
all_db_permissions = models.Permission.objects.all()
# 获取路由里面所有的 URL
route_dict = get_all_routes_url(ignore_namespace_list=['admin', 'rabc'])
# print('--->', route_dict)
# 数据库里面的所有权限的别名
db_permission_name_set = set([i.name for i in all_db_permissions])
# 路由系统中的所有权限的别名
route_permission_name_set = set([i for i in route_dict])
# print('===>', route_permission_name_set)
# 如果请求的类型
if request.method == 'POST' and action_type == 'add':
add_formset = AddFormSet(request.POST)
if add_formset.is_valid():
print('>>>', add_formset.cleaned_data)
# 批量创建好新建对象
permission_obj_list = [models.Permission(**i) for i in add_formset.cleaned_data]
# 批量保存
query_set = models.Permission.objects.bulk_create(permission_obj_list)
# 创建完成之后,添加进 数据库name列表,方便跳转展示
for i in query_set:
db_permission_name_set.add(i.name)
else:
raise Exception('参数非法!')
# 即将添加进数据库的别名 路由 - 数据库
add_name_set = route_permission_name_set - db_permission_name_set
add_formset = AddFormSet(initial=[row for name, row in route_dict.items() if name in add_name_set])
# for name, row in route_dict.items():
# print(row)
# 即将被删除的别名 数据库 - 路由
del_name_set = db_permission_name_set - route_permission_name_set
del_formset = FormSet(queryset=models.Permission.objects.filter(name__in=del_name_set))
# 即将被更新的别名 数据库和路由里面都有的
update_name_set = route_permission_name_set & db_permission_name_set
update_formset = FormSet(queryset=models.Permission.objects.filter(name__in=update_name_set))
if request.method == 'POST' and action_type == 'update':
print('更新!!!')
update_formset = FormSet(request.POST)
if update_formset.is_valid():
update_formset.save()
update_formset = FormSet(queryset=models.Permission.objects.filter(name__in=update_name_set))
# for i in add_formset:
# print('=================================================')
# print(i)
return render(request,
'show_permissions/multi_permission.html',
{
'del_formset': del_formset,
'update_formset': update_formset,
'add_formset': add_formset
})
3.在模板中
代码语言:javascript
复制{% extends 'layout.html' %}
{% block content %}
<form action="?type=add" method="post">
{% csrf_token %}
{{ add_formset.management_form }}
<div class="panel panel-primary" style="margin-top: 10px">
<div class="panel-heading">
<h3 class="panel-title">待新建权限列表
<button class="right btn btn-success btn-xs" style="padding: 2px 8px;margin: -3px;">
<i class="fa fa-save" aria-hidden="true"></i>
新建并保存
</button>
</h3>
</div>
<div style="margin-left: 10px"><h5>注意:注意:路由系统中存在,但数据库中不存在的路由。</h5></div>
<div class="panel-body">
<table class="table table-bordered table-bordered">
<thead>
<tr>
<th>序号</th>
<th>名称</th>
<th>URL</th>
<th>别名</th>
<th>二级菜单</th>
<th>一级菜单</th>
</tr>
</thead>
<tbody>
{% for form in add_formset %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ form.title }}<span>{{ form.title.errors.0 }}</span></td>
<td>{{ form.URL }}</td>
<td>{{ form.name }}</td>
<td>{{ form.parent }}</td>
<td>{{ form.menu }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</form>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">待删除的权限列表</h3>
</div>
<div style="margin-left: 10px"><h5>数据库中存在但路由系统里面不存在的路由。</h5></div>
<div class="panel-body">
<table class="table table-bordered table-bordered">
<thead>
<tr>
<th>序号</th>
<th>名称</th>
<th>URL</th>
<th>别名</th>
<th>二级菜单</th>
<th>一级菜单</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for form in del_formset %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ form.title }}</td>
<td>{{ form.URL }}</td>
<td>{{ form.name }}</td>
<td>{{ form.parent }}</td>
<td>{{ form.menu }}</td>
<td>
<a href="" style="color: firebrick">
<li class="fa fa-remove"></li>
删除
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<form action="?type=update" method="post">
{% csrf_token %}
{{ update_formset.management_form }}
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">待更新的权限列表
<button class="right btn btn-success btn-xs" style="padding: 2px 8px;margin: -3px;">
<i class="fa fa-save" aria-hidden="true"></i>
更新并保存
</button>
</h3>
</div>
<div style="margin-left: 10px"><h5>注意:数据库和路由系统都存在的路由。</h5></div>
<div class="panel-body">
<table class="table table-bordered table-bordered">
<thead>
<tr>
<th>序号</th>
<th>名称</th>
<th>URL</th>
<th>别名</th>
<th>二级菜单</th>
<th>一级菜单</th>
</tr>
</thead>
<tbody>
{% for form in update_formset %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ form.title }}</td>
<td>{{ form.URL }}</td>
<td>{{ form.name }}</td>
<td>{{ form.parent }}</td>
<td>{{ form.menu }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</form>
{% endblock %}
2.权限的分配
1.在views中(注释可不看)
代码语言:javascript
复制# 分配权限
def distribute_permission(request):
# 用户id,点击完某个用户之后,用户的 id 会被拼接在 url 中
uid = request.GET.get('uid')
# 角色id
rid = request.GET.get('rid')
if request.method == 'POST' and request.POST.get('postType') == 'role':
print('-->role')
user = models.User.objects.filter(id=uid).first()
if not user:
return HttpResponse('用户不存在!')
print('提交更新角色信息-->', request.POST.getlist('roles'))
user.roles.set(request.POST.getlist('roles'))
if request.method == 'POST' and request.POST.get('postType') == 'permission' and rid:
print('-->permission')
role = models.Role.objects.filter(id=rid).first()
if not role:
return HttpResponse('角色不存在!')
role.permissions.set(request.POST.getlist('permissions'))
# 拿到所有的用户
user_list = models.User.objects.all()
# 根据用户id获取用户角色, roles 是多对多,取的是 一组 id,一会儿试试!!!!!!!!!!!
user_has_roles = models.User.objects.filter(id=uid).values('id', 'roles')
"""
user_has_roles = {{'用户id': XX,'角色id': XX}, ...}
"""
# 用户拥有的 角色--> 根据用户id获取觉得id
user_has_roles_dict = {item['roles']: None for item in user_has_roles}
"""
user_has_roles_dict = {{'角色id': None}, ...}
"""
# 拿到所有的角色
roles_list = models.Role.objects.all()
"""
role_list = [{'role_name': XX, 'permissions': XX}, ...]
"""
# 如果有角色 id
if rid:
role_has_permissions = models.Role.objects.filter(id=rid).values('id', 'permissions')
# 如果只有用户 id,没有角色 id
elif uid and not rid:
# 筛选当前用户
user = models.User.objects.filter(id=uid).first()
if not user:
return HttpResponse('用户不存在!')
# 根据觉得筛选出角色所拥有的 id
role_has_permissions = user.roles.values('id', 'permissions')
else:
role_has_permissions = []
role_has_permissions_dict = {item['permissions']: None for item in role_has_permissions}
# 拿到所有的菜单的 id 和 title
menu_queryset = models.Menu.objects.all().values('id', 'title')
"""
menu_queryset = [{'一级菜单id': XX, '一级菜单title': XX}, ...]
"""
# 权限字典
menu_dict = {}
# 所有的菜单
all_menu_list = []
for item in menu_queryset:
"""
item = {'一级菜单id': XX, '一级菜单title': XX}
"""
item['children'] = [] # menu一级菜单新开一个 children,存放二级权限
"""
item = {'一级菜单id': XX, '一级菜单title': XX, children: []}
"""
menu_dict[item['id']] = item # 权限字典里面
"""
menu_dict = {'一级菜单id': {'一级菜单id': XX, '一级菜单title': XX, children: []}, ...}
"""
all_menu_list.append(item)
"""
all_menu_list = [{'一级菜单id': XX, '一级菜单title': XX, children: []} , ...]
"""
# 还有一些没有分配的,比如 login、logout
other = {'id': None, 'title': '其他', 'children': []}
menu_dict[None] = other
"""
menu_dict = {'一级菜单id': {'一级菜单id': XX, '一级菜单title': XX, children: []},
...
...,
None: {'id': None, 'title': '其他', 'children': []}}
"""
all_menu_list.append(other)
"""
all_menu_list = [{'一级菜单id': XX, '一级菜单title': XX, 'children': []},
...
...,
{'id': None, 'title': '其他', 'children': []}
]
"""
# 二级菜单权限(父权限)
parent_queryset = models.Permission.objects.filter(menu_id__isnull=False).values('id', 'title', 'menu_id')
"""
parent_queryset = [{'二级菜单id': XX, '二级菜单title': XX, '二级菜单menu_id': XX}, ...]
"""
# 定义二级菜单的字典
parent_permission_dict = {}
for item in parent_queryset:
"""
item = {'二级菜单id': XX, '二级菜单title': XX, '二级菜单menu_id': XX}
"""
item['children'] = [] # 存放子权限
"""
item = {'二级菜单id': XX, '二级菜单title': XX, '二级菜单menu_id': XX, 'children': []}
"""
nid = item['id'] # 二级菜单(父权限)的 id
menu_id = item['menu_id'] # 二级菜单(父权限)的 一级菜单的 菜单id (一级菜单id)
parent_permission_dict[nid] = item
"""
parent_permission_dict = {{'二级菜单id': XX, '二级菜单title': XX, '二级菜单menu_id': XX, 'children': []}, ...}
"""
menu_dict[menu_id]['children'].append(item)
"""
menu_dict = {'一级菜单id': {'一级菜单id': XX, '一级菜单title': XX, children:
[{'二级菜单id': XX, '二级菜单title': XX, '二级菜单menu_id': XX, 'children': []}]},
...
...,
None: {'id': None, 'title': '其他', 'children': []}}
☆☆☆☆同时:!!!它的 menu children里面 也加一份????☆☆☆☆☆
all_menu_list = [{'一级菜单id': XX, '一级菜单title': XX, 'children':
[{'二级菜单id': XX, '二级菜单title': XX, '二级菜单menu_id': XX, 'children': []}]},
...
...,
{'id': None, 'title': '其他', 'children': []}
]
"""
# 拿到所有的子权限
son_permission_queryset = models.Permission.objects.filter(menu__isnull=True).values('id', 'title', 'parent_id')
"""
son_permission_queryset = [{'子权限id': XX, '子权限title': XX, '子权限parent_id': XX}, ...]
"""
for item in son_permission_queryset:
"""
item = {'子权限id': XX, '子权限title': XX, '子权限parent_id': XX}
"""
pid = item['parent_id'] # 子权限的父权限(二级菜单)的id
if not pid: # 还有部分没有挂名的 url login、logout
menu_dict[None]['children'].append(item)
"""
menu_dict = {'一级菜单id': {'一级菜单id': XX, '一级菜单title': XX, children: []},
...
...,
None: {'id': None, 'title': '其他', 'children':
[{'子权限id': XX, '子权限title': XX, '子权限parent_id': XX}, ]}}
☆☆☆☆同时:!!!下面菜单的 None children 也有一份????☆☆☆☆☆
all_menu_list = [{'一级菜单id': XX, '一级菜单title': XX, 'children':
[{'二级菜单id': XX, '二级菜单title': XX, '二级菜单menu_id': XX, 'children': []}]},
...
...,
{'id': None, 'title': '其他', 'children':
[{'子权限id': XX, '子权限title': XX, '子权限parent_id': XX},]}
]
menu_dict = {'一级菜单id': {'一级菜单id': XX, '一级菜单title': XX, children:
[{'二级菜单id': XX, '二级菜单title': XX, '二级菜单menu_id': XX, 'children': []}]},
...
...,
None: {'id': None, 'title': '其他', 'children':
[{'子权限id': XX, '子权限title': XX, '子权限parent_id': XX}]}}
"""
continue
parent_permission_dict[pid]['children'].append(item)
"""
parent_permission_dict = {'二级菜单id': {'二级菜单id': XX, '二级菜单title': XX, '二级菜单menu_id': XX,
'children':[{'子权限id': XX, '子权限title': XX, '子权限parent_id': XX}]},
...}
☆☆☆☆同时:!!!下面俩二级菜单子的 children 也有一份????☆☆☆☆☆
menu_dict = {'一级菜单id': {'一级菜单id': XX, '一级菜单title': XX, children:
[{'二级菜单id': XX, '二级菜单title': XX, '二级菜单menu_id': XX, 'children':
[{'子权限id': XX, '子权限title': XX, '子权限parent_id': XX}, ...]}]},
...
...,
None: {'id': None, 'title': '其他', 'children':
[{'子权限id': XX, '子权限title': XX, '子权限parent_id': XX}]}}
==== {1: {'id': 1, 'title': '信息管理', 'children':
[{'id': 1, 'title': '客户列表', 'menu_id': 1, 'children':
[{'id': 2, 'title': '添加客户', 'parent_id': 1}, {'id': 3, 'title': '编辑客户', 'parent_id': 1}, {'id': 4, 'title': '删除客户', 'parent_id': 1}, {'id': 12, 'title': '测试', 'parent_id': 1}]}]},
2: {'id': 2, 'title': '财务管理', 'children':
[{'id': 5, 'title': '缴费记录', 'menu_id': 2, 'children':
[{'id': 6, 'title': '添加缴费记录', 'parent_id': 5}, {'id': 7, 'title': '编辑缴费记录', 'parent_id': 5}, {'id': 8, 'title': '删除缴费记录', 'parent_id': 5}]}, {'id': 13, 'title': '阿达是大所', 'menu_id': 2, 'children': []}]},
None: {'id': None, 'title': '其他', 'children': []}}
all_menu_list = [{'一级菜单id': XX, '一级菜单title': XX, 'children':
[{'二级菜单id': XX, '二级菜单title': XX, '二级菜单menu_id': XX, 'children':
[{'子权限id': XX, '子权限title': XX, '子权限parent_id': XX}, ...]}]},
...
...,
{'id': None, 'title': '其他', 'children':
[{'子权限id': XX, '子权限title': XX, '子权限parent_id': XX}]}
]
---- [{'id': 1, 'title': '信息管理', 'children':
[{'id': 1, 'title': '客户列表', 'menu_id': 1, 'children':[{'id': 2, 'title': '添加客户', 'parent_id': 1}, {'id': 3, 'title': '编辑客户', 'parent_id': 1}, {'id': 4, 'title': '删除客户', 'parent_id': 1}, {'id': 12, 'title': '测试', 'parent_id': 1}]}]},
{'id': 2, 'title': '财务管理', 'children': [{'id': 5, 'title': '缴费记录', 'menu_id': 2, 'children': [{'id': 6, 'title': '添加缴费记录', 'parent_id': 5}, {'id': 7, 'title': '编辑缴费记录', 'parent_id': 5}, {'id': 8, 'title': '删除缴费记录', 'parent_id': 5}]}, {'id': 13, 'title': '阿达是大所', 'menu_id': 2, 'children': []}]},
{'id': None, 'title': '其他', 'children': []}]
"""
# print('====', menu_dict)
print('----', all_menu_list)
return render(request, 'show_permissions/distribute_permissions.html',
{
'user_list': user_list, # 用户列表
'role_list': roles_list, # 角色列表
'user_has_roles_dict': user_has_roles_dict, # 用户有哪些权限,里面是权限id,做选中样式
'role_has_permissions_dict': role_has_permissions_dict, # 角色有哪些权限,做选中样式
'all_menu_list': all_menu_list, # 权限列表
'uid': uid,
'rid': rid
})
2.在模板中
代码语言:javascript
复制{% extends 'layout.html' %}
{% block css %}
<style>
.username_active,.role_name_active {
font-weight: bold;
color: red;
font-size: 15px;
}
.table_menu {
font-size: 16px;
font-weight: bold;
background-color: rgb(116, 140, 183);
}
.table_parent {
font-size: 15px;
font-weight: bold;
}
.table_children {
margin-left: 20px;
}
</style>
{% endblock %}
{% block content %}
<div class="container-fluid" style="margin-top: 10px">
<div class="row">
<div class="col-sm-3">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">用户信息</h3>
</div>
<div class="panel-body">
<ul>
{% for user in user_list %}
<li class= {% if user.id|safe == uid %} "username_active" {% endif %}>
<a href="?uid={{ user.id }}">{{ user.name }}</a></li>
{% endfor %}
</ul>
</div>
</div>
</div>
<div class="col-sm-3">
<form action="" method="post">
{% csrf_token %}
<input type="hidden" name="postType" value="role">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">角色
{% if uid %}
<button type="submit" class="right btn btn-success btn-xs"
style="padding: 2px 8px;margin: -3px;">
<i class="fa fa-save" aria-hidden="true"></i>
保存
</button>
{% endif %}
</h3>
</div>
<h5 style="margin-left: 5%">
<li class="fa fa-exclamation-triangle fa-1x" style="color: #2F72AB"></li>
点击用户后才能为其分配角色~
</h5>
<div class="panel-body">
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>角色</th>
<th>选择</th>
</tr>
</thead>
<tbody>
{% for role in role_list %}
<tr>
{# {% load templates_for_model %}#}
<td class={% if role.id|safe == rid %}
"role_name_active"
{% endif %}><a href="?rid={{ role.id }}">{{ role.role_name }}</a></td>
{# <td><a href="{% add_role_id request role.id %}">{{ role.role_name }}</a></td>#}
{# <td>{{ role.role_name }}</td>#}
<td>
{% if role.id in user_has_roles_dict %}
<input type="checkbox" name="roles" value="{{ role.id }}" checked/>
{% else %}
<input type="checkbox" name="roles" value="{{ role.id }}"/>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</form>
</div>
<div class="col-sm-6">
<form action="" method="post">
{% csrf_token %}
<input type="hidden" name="postType" value="permission">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">权限分配
{% if rid %}
<button type="submit" class="right btn btn-success btn-xs"
style="padding: 2px 8px;margin: -3px;">
<i class="fa fa-save" aria-hidden="true"></i>
保存
</button>
{% endif %}
</h3>
</div>
<h5 style="margin-left: 5%">
<li class="fa fa-exclamation-triangle fa-1x" style="color: #2F72AB"></li>
点击用角色后才能为其分配权限~
</h5>
<div class="panel-body">
<table class="table table-hover"
style="border: solid 1px rgb(51,122,183); border-top: solid 2px rgb(51,122,183)">
<tbody>
{% for menu in all_menu_list %}
<tr class="table_menu">
<td><i class="fa fa-caret-down" aria-hidden="true"></i> {{ menu.title }}
</td>
</tr>
{% for p_permission in menu.children %}
<tr>
<td>
<div class="table_parent">
{% if p_permission.id in role_has_permissions_dict %}
<input type="checkbox" name="permissions"
value="{{ p_permission.id }}" checked>
{{ p_permission.title }}
{% else %}
<input type="checkbox" name="permissions"
value="{{ p_permission.id }}">{{ p_permission.title }}
{% endif %}
</div>
<div class="table_children">
{% for child_permission in p_permission.children %}
{% if child_permission.id in role_has_permissions_dict %}
<input type="checkbox" name="permissions"
value="{{ child_permission.id }}" checked>
{{ child_permission.title }}
{% else %}
<input type="checkbox" name="permissions"
value="{{ child_permission.id }}">
{{ child_permission.title }}
{% endif %}
{% endfor %}
</div>
</td>
</tr>
{% endfor %}
{% endfor %}
</tbody>
</table>
</div>
</div>
</form>
</div>
</div>
</div>
{% endblock %}