权限组件(14):分配权限功能
效果图:
一、URL配置
rbac/url.py
... from django.urls import re_path ... from rbac.views import menu urlpatterns = [ # 分配权限 re_path(r'^distribute/permissions/$', menu.distribute_permissions, name='distribute_permissions'), ]
二、视图函数
rbac/views/menu.py
... from django.shortcuts import HttpResponse, render from rbac import models ... ... def distribute_permissions(request): """ 权限分配 :param request: :return: """ user_id = request.GET.get('uid') user_object = models.UserInfo.objects.filter(id=user_id).first() if not user_object: user_id = None role_id = request.GET.get('rid') role_object = models.Role.objects.filter(id=role_id).first() if not role_object: role_id = None if request.method == 'POST' and request.POST.get('type') == 'role': role_id_list = request.POST.getlist('roles') # 用户和角色的关系添加到第三张表(关系表) if not user_object: return HttpResponse('请选择用户,然后再分配角色') user_object.roles.set(role_id_list) if request.method == 'POST' and request.POST.get('type') == 'permission': permission_id_list = request.POST.getlist('permissions') if not role_object: return HttpResponse('请选择角色然后再分配权限!') role_object.permissions.set(permission_id_list) # 获取当前用户拥有的所有角色 if user_id: user_has_roles = user_object.roles.all() else: user_has_roles = [] user_has_roles_dict = {item.id: None for item in user_has_roles} # 字典查找速度更快 # 获取当前用户拥有的所有权限 # 如果选中了角色,优先显示选中角色所拥有的权限 # 如果没有选角色,才显示用户所拥有的权限 if role_object: # 选择了角色 user_has_permissions = role_object.permissions.all() user_has_permissions_dict = {item.id: None for item in user_has_permissions} elif user_object: # 未选择角色,但是选择了用户 user_has_permissions = user_object.roles.filter(permissions__id__isnull=False).values( 'id', 'permissions').distinct() user_has_permissions_dict = {item['permissions']: None for item in user_has_permissions} else: user_has_permissions_dict = {} user_list = models.UserInfo.objects.all() all_role_list = models.Role.objects.all() # 用到的知识点:字典里的值和列表里的值用的是同一个内存地址,如果改了字典里的值,列表里相应的值也会被改。 # 所有的一级菜单 all_menu_list = models.Menu.objects.all().values('id', 'title') all_menu_dict = {} for menu_obj in all_menu_list: menu_obj['children'] = [] # 用于放二级菜单 all_menu_dict[menu_obj['id']] = menu_obj # 所有的二级菜单 all_second_menu_list = models.Permission.objects.filter(menu__isnull=False).values('id', 'title', 'menu_id') all_second_menu_dict = {} for second_menu_obj in all_second_menu_list: second_menu_obj['children'] = [] # 用于放三级菜单(具体权限) all_second_menu_dict[second_menu_obj['id']] = second_menu_obj menu_id = second_menu_obj['menu_id'] all_menu_dict[menu_id]['children'].append(second_menu_obj) # 所有的三级菜单(不能做菜单的权限) all_permission_list = models.Permission.objects.filter(menu__isnull=True).values('id', 'title', 'pid_id') for permission_obj in all_permission_list: pid = permission_obj['pid_id'] if not pid: # 表示数据不合法,也就是菜单和父权限都没有,那就不处理了 continue all_second_menu_dict[pid]['children'].append(permission_obj) """ [ { id:1, title:'业务管理', children:[ { 'id':1, title:'账单列表', children:[ {'id':12, 'title':'添加账单'} ] }, {'id':11, 'title':'客户列表'}, ] }, ] """ context = { 'user_list': user_list, 'role_list': all_role_list, 'all_menu_list': all_menu_list, 'user_id': user_id, 'user_has_roles_dict': user_has_roles_dict, 'user_has_permissions_dict': user_has_permissions_dict, 'role_id': role_id } return render(request, 'rbac/distribute_permissions.html', context) ...
三、模板
rbac/templates/distribute_permissions.html
{% extends 'layout.html' %} {% load rbac %}] {% block css %} <style> table { font-size: 12px; } .user-area ul { padding-left: 20px; } .user-area li { cursor: pointer; padding: 2px 0; } .user-area li a { display: block; } .user-area li.active { font-weight: bold; color: red; } .user-area li.active a { color: red; } .role-area tr td a { display: block; } .role-area tr.active { background-color: #f1f7fd; border-left: 3px solid #fdc00f; } .panel-body { font-size: 12px; } .permission-area tr.root { background-color: #f1f7fd; } .permission-area tr.root td i { margin: 3px; } .permission-area .node { } .permission-area .node input[type='checkbox'] { margin: 0 5px; } .permission-area .node .parent { padding: 5px 0; } .permission-area .node label { font-weight: normal; margin-bottom: 0; font-size: 12px; } .permission-area .node .children { padding: 0 0 0 20px; } .permission-area .node .children .child { display: inline-block; margin: 2px 5px; } .select-help { float: right; } .select-help label { font-weight: normal; cursor: pointer; } .select-help .check-all { float: left; display: inline-block; margin-right: 8px; } </style> {% endblock css %} {% block content %} <div class="luffy-container"> <div class="col-md-3 user-area"> <div class="panel panel-default"> <div class="panel-heading"> <i class="fa fa-book" aria-hidden="true">用户信息</i> </div> <div class="panel-body"> <ul> {% for user in user_list %} <li class="{% if user.id|safe == user_id %} active {% endif %}"> <a href="?uid={{ user.id }}">{{ user.name }}</a> </li> {% endfor %} </ul> </div> </div> </div> <div class="col-md-3 role-area"> <form method="post"> {% csrf_token %} <input type="hidden" name="type" value="role"> <div class="panel panel-default"> <!-- Default panel contents --> <div class="panel-heading"> <i class="fa fa-flag" aria-hidden="true">角色信息</i> {% if user_id %} <button class="right btn btn-success" style="padding: 2px 8px;margin:-3px"> <i class="fa fa-plus-circle" aria-hidden="true">保存</i> </button> {% endif %} <div class="panel-body"> 提示:点击用户才能为其分配权限 </div> </div> <table class="table"> <thead> <tr> <th>角色</th> <th>选项</th> </tr> </thead> <tbody> {% for role in role_list %} <tr class="{% if role.id|safe == role_id %}active{% endif %}"> <td> {% if user_id %} <a href="?uid={{ user_id }}&rid={{ role.id }}">{{ role.title }}</a> {% else %} <a href="?rid={{ role.id }}">{{ role.title }}</a> {% endif %} </td> <td> <input type="checkbox" name="roles" value="{{ role.id }}" {% if role.id in user_has_roles_dict %}checked{% endif %}/> <!-- 不用转义 --> </td> </tr> {% endfor %} </tbody> </table> </div> </form> </div> <div class="col-md-6 permission-area"> <form method="post"> {% csrf_token %} <input type="hidden" name="type" value="permission"> <div class="panel panel-default"> <div class="panel-heading"> <i class="fa fa-flag" aria-hidden="true">权限分配</i> {% if role_id %} <button class="right btn btn-success btn-xs" style="padding: 2px 8px;margin:-3px"> <i class="fa fa-plus-circle" aria-hidden="true">保存</i> </button> {% endif %} </div> <div class="panel-body" style="color: #d4d4d4;padding:10px 5px;"> 提示:点击角色后,才能为其分配权限 </div> <table class="table"> <tbody> {% for menu in all_menu_list %} <tr class="root"> <td> <i class="fa fa-caret-down" aria-hidden="true"></i> {{ menu.title }} <div class="select-help"> <div class="check-all"> <label for="check_all_{{ menu.id }}">全选</label> <input type="checkbox" id="check_all_{{ menu.id }}"> </div> </div> </td> </tr> {% if menu.children %} <tr class="node"> <td> {% for second_menu in menu.children %} <div class="parent"> <input type="checkbox" id="permission_{{ second_menu.id }}" name="permissions" value="{{ second_menu.id }}" {% if second_menu.id in user_has_permissions_dict %}checked{% endif %}/> <label for="permission_{{ second_menu.id }}">{{ second_menu.title }} (菜单)</label> </div> <div class="children"> {% for permission in second_menu.children %} <div class="child"> <input type="checkbox" id="permission_{{ permission.id }}" name="permissions" value="{{ permission.id }}" {% if permission.id in user_has_permissions_dict %}checked{% endif %}/> <label for="permission_{{ permission.id }}">{{ permission.title }}</label> </div> {% endfor %} </div> {% endfor %} </td> </tr> {% endif %} {% endfor %} </tbody> </table> </div> </form> </div> </div> {% endblock content %} {% block js %} <script> $(function () { $('.check-all input:checkbox').change(function () { $(this).parents('.root').next().find(':checkbox').prop('checked', $(this).prop('checked')) //等于当前(全选)的值 // 使用attr设置checked返回的是string类型,用prop才返回bool类型。 }) }) </script> {% endblock js %}