权限组件(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 %}

 

参考:jquery中arrt()和prop()的区别

 

posted @ 2019-03-16 10:03  梁少华  阅读(748)  评论(0编辑  收藏  举报