权限分配实现思路

先上一张,效果图。 OK
开始做:
用户信息  和 角色。很容易就能搞成。 只需要从数据库取出。 menu  和 role 两张表的全部数据, 再模板进行循环的渲染就行了。

    all_user_queryset = models.UserInfo.objects.all()
    all_role_queryset = models.Role.objects.all()

 拿到数据,前端直接渲染就好了!

{% extends "layout.html" %}
{% block css %}
    <style type="text/css">
        tr.active {
            border-left: #eea236 solid 2px;
        }
    </style>
{% endblock %}
{% load rbac_tags %}
{% block content %}
    <div class="luffy-container">
        <div class="col-md-3">
            <div class="panel panel-default">
                <!-- Default panel contents -->
                <div class="panel-heading"><i class="fa fa-book" aria-hidden="true"></i>员工信息</div>
                <div class="panel panel-body">
                    <ul>
                        {% for user in all_user_list %}
                            <li><a href="">{{ user.name }}</a></li>
                        {% endfor %}
                    </ul>
                </div>
            </div>
        </div>
        <div class="col-md-4">
            <div class="panel panel-default">
                <div class="panel-heading"><i class="fa fa-binoculars" aria-hidden="true"></i>角色信息</div>
                <div class="panel panel-body">
                提示:点击用户后才能为其分配角色
                    <table class="table table-condensed">
                        <thead>
                        <tr>
                            <th>角色</th>
                            <th>选项</th>
                        </tr>
                        </thead>
                        <tbody>
                        {% for role in all_role_list %}
                            <tr>
                                <td><a href="">{{role.title}}</a></td>
                                <td><input type="checkbox" name="roles" value="{{ role.id }}"></td>
                            </tr>
                        {% endfor %}
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
{% endblock %}
这部分,我也没搞 样式!  看自己心情!

最后的  权限分配这里,才是重点:
  可以看到的是, 这有一个层级结构。  业务管理 为一级菜单。 账单列表为二级菜单。 其余的就是 各属于二级菜单之下的 权限。
所以如果 在模板进行渲染的时候, 是一个 列表嵌套字典的格式,会容易许多:
  比如这样的:

{
    'mid': 1,
    'title': '用户管理',
    'children': [{
        'id': 1,
        'title': '客户列表',
        'menu_id': 1,
        'children': [{
            'id': 2,
            'title': '添加客户',
            'pid_id': 1
        }, {
            'id': 3,
            'title': '修改客户',
            'pid_id': 1
        }, {
            'id': 4,
            'title': '删除客户',
            'pid_id': 1
        }, {
            'id': 5,
            'title': '批量导入',
            'pid_id': 1
        }, {
            'id': 6,
            'title': '下载模板',
            'pid_id': 1
        }]
    }]
}

 这样子中三层的,层级结构。  传给模板的时候,就只需要。 三层循环就可以了!
      如果你想递归, 我也有 递归的方法。(一个用于渲染评论树的代码)
第一步也是没啥好所的, 先从数据库把 所有的数据取出来:

    # 所有的一级菜单
    all_menu_queryset = models.Menu.objects.values("mid", "title")
    # 所有的二级菜单
    all_second_menu_queryset = models.Permission.objects.filter(menu_id__isnull=False).values("id", "title", "menu_id")
    # 所有的不是二级菜单的权限
    all_permission_queryset = models.Permission.objects.filter(menu_id__isnull=True).values("id", "title", "pid_id")

这里有一点 必须要说明:  Python 的赋值是使用的, 引用机制。 所以才会有下面方法的, 构造数据的方式:
这里可能会有疑惑,为什么更新的是字典。 但是最后用的却是最初循环的列表呢?

    all_menu_dict = {}  # 只是为了,在循环中查找数据方便,创建的字典
    for item in all_menu_queryset:
        item["children"] = []
        all_menu_dict[item.get("mid")] = item
# 我这里在循环的时候, 给all_menu_queryset中每一个item(这是一个字典)添加了一个 ["children"] = []。 
注意!!!! 我是先添加了一个键值对, 才保存到all_menu_dict字典中的。 所以当我下面的循环,在对这个字典中的 ["children"] = [] 这个列表进行添加操作
的时候。 改变的不仅仅是 我这个字典的数据。 会连带着all_menu_queryset中的数据,也会发生变化! 因为python 的引用机制。 大家使用的都是同一块内存地址

all_second_menu_dict
= {} for row in all_second_menu_queryset: row["children"] = [] all_second_menu_dict[row.get("id")] = row menu_id = row.get("menu_id") # 如果没数据库没有做关联的话, 这里要判断以下 是否有这个 menu_id all_menu_dict.get(menu_id).get("children").append(row) # 因为我的数据库是做了关联的,所以才能在这里直接查找赋值。 for row in all_permission_queryset: pid_id = row.get("pid_id") if not pid_id: continue all_second_menu_dict.get(pid_id).get("children").append(row)

queryset 是一种类似于, 列表的结构。  最终所有的数据, 都保存在了 all_menu_queryset 这个里面。

然后就是, 所有判断,当前用户是谁。 让权限表,角色表。  让相应的 checkbox 带上 checked 属性。 这里就需要让后台知道当前用户点击的

还是 老套路。 在用户和角色的的 标签上!加上 ?uid=1  和 ?uid=1&rid=1。 如果忘了,就去前面的博客复习。
https://www.cnblogs.com/chengege/p/10710371.html

然后是,视图部分代码逻辑:

    user_id = request.GET.get('uid')
    role_id = request.GET.get('rid')
    user_obj = models.UserInfo.objects.filter(pk=user_id).first()
    role_obj = models.Role.objects.filter(pk=role_id).first()

    if not user_obj:
        user_id = None

    if not role_obj:
        role_id = None

    # 获取当前用户所拥有的角色. 进行默认选择
    if user_id:
        user_has_role = user_obj.roles.all().values("id")
    else:
        user_has_role = []
    user_has_role_dict = {item["id"]: None for item in user_has_role}

    # 如果选中了角色,优先显示选中的角色,拥有的权限。 如果没有选择角色,才显示用户的所有权限
    if role_obj:
        user_has_permissions = role_obj.permissions.all()
        user_has_permissions_dict = {item.id: None for item in user_has_permissions}
    elif user_obj:
        user_has_permissions = user_obj.roles.values("permissions__id").distinct()  # 获取当前用户所拥有的所有权限
        user_has_permissions_dict = {item["permissions__id"]: None for item in user_has_permissions}
    else:
        user_has_permissions_dict = {}
View Code

前端使用同一个,user_has_permissions_dict 。在后台 进行判断。  如果用户选中了角色,优先显示选中的角色,拥有的权限。 如果没有选择角色,才显示用户的所有权限。
最后是,提交保存的代码:

    if request.method == "POST" and request.POST.get("type") == "role":
        role_id_list = request.POST.getlist("roles")
        if not user_obj:
            return HttpResponse("请选择用户,不要自己添加input标签。烦得很")
        user_obj.roles.set(role_id_list)  # 通过用户找到 roles 然后set 向他们的关系表。 更新数据
    if request.method == "POST" and request.POST.get("type") == "permission":
        permission_id_list = request.POST.getlist("permissions")
        if not user_obj or not role_obj:
            return HttpResponse("请选择用户,不要自己添加input标签。烦得很")
        role_obj.permissions.set(permission_id_list)
View Code

这里用到了, ORM 中。 对多对多关系表,更新的 set() 方法。

头昏脑涨:太晚了!先放上所有代码:

def distribute_permission(request):
    '''
    权限分配
    :param request:
    :return:
    '''
    user_id = request.GET.get('uid')
    role_id = request.GET.get('rid')
    user_obj = models.UserInfo.objects.filter(pk=user_id).first()
    role_obj = models.Role.objects.filter(pk=role_id).first()


    if request.method == "POST" and request.POST.get("type") == "role":
        role_id_list = request.POST.getlist("roles")
        if not user_obj:
            return HttpResponse("请选择用户,不要自己添加input标签。烦得很")
        user_obj.roles.set(role_id_list)  # 通过用户找到 roles 然后set 向他们的关系表。 更新数据
    if request.method == "POST" and request.POST.get("type") == "permission":
        permission_id_list = request.POST.getlist("permissions")
        if not user_obj or not role_obj:
            return HttpResponse("请选择用户,不要自己添加input标签。烦得很")
        role_obj.permissions.set(permission_id_list)

    if not user_obj:
        user_id = None

    if not role_obj:
        role_id = None

    # 获取当前用户所拥有的角色. 进行默认选择
    if user_id:
        user_has_role = user_obj.roles.all().values("id")
    else:
        user_has_role = []
    user_has_role_dict = {item["id"]: None for item in user_has_role}

    # 如果选中了角色,优先显示选中的角色,拥有的权限。 如果没有选择角色,才显示用户的所有权限
    if role_obj:
        user_has_permissions = role_obj.permissions.all()
        user_has_permissions_dict = {item.id: None for item in user_has_permissions}
    elif user_obj:
        user_has_permissions = user_obj.roles.values("permissions__id").distinct()  # 获取当前用户所拥有的所有权限
        user_has_permissions_dict = {item["permissions__id"]: None for item in user_has_permissions}
    else:
        user_has_permissions_dict = {}

    all_user_queryset = models.UserInfo.objects.all()
    all_role_queryset = models.Role.objects.all()

    # 所有的一级菜单
    all_menu_list = models.Menu.objects.values("mid", "title")
    # 所有的二级菜单
    all_second_menu_queryset = models.Permission.objects.filter(menu_id__isnull=False).values("id", "title", "menu_id")
    # 所有的不是二级菜单的权限
    all_permission_queryset = models.Permission.objects.filter(menu_id__isnull=True).values("id", "title", "pid_id")

    all_menu_dict = {}
    for item in all_menu_list:
        item["children"] = []
        all_menu_dict[item.get("mid")] = item

    all_second_menu_dict = {}
    for row in all_second_menu_queryset:
        row["children"] = []
        all_second_menu_dict[row.get("id")] = row

        menu_id = row.get("menu_id")
        all_menu_dict.get(menu_id).get("children").append(row)

    for row in all_permission_queryset:
        pid_id = row.get("pid_id")
        if not pid_id:
            continue
        all_second_menu_dict.get(pid_id).get("children").append(row)

    return render(request, "rbac/distribute_permissions.html",
                  {"all_user_list": all_user_queryset,
                   "all_role_list": all_role_queryset,
                   "all_menu_queryset": all_menu_list,
                   "user_id": user_id,
                   "role_id": role_id,
                   "user_has_role_dict": user_has_role_dict,
                   "user_has_permissions_dict": user_has_permissions_dict})
试图函数
{% extends "layout.html" %}
{% block css %}
    <style>
        table {
            font-size: 12px;
        }
        .panel-body{font-size: 12px;margin-bottom: 0}

        .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 %}
{% load rbac_tags %}
{% block content %}
    <div class="luffy-container">
        <div class="col-md-3 user-area">
            <div class="panel panel-default">
                <!-- Default panel contents -->
                <div class="panel-heading"><i class="fa fa-book" aria-hidden="true"></i>员工信息</div>
                <div class="panel panel-body">
                    <ul>
                        {% for user in all_user_list %}
                            <li class="{% if user_id == user.id|safe %}active{% endif %}">
                                <a href="?uid={{ user.id }}">{{ user.name }}</a></li>
                        {% endfor %}
                    </ul>
                </div>
            </div>
        </div>


        <div class="col-md-3 role-area">
            <div class="panel panel-default">
                <form method="post">
                    {% csrf_token %}
                    <input type="hidden" name="type" value="role">
                    <div class="panel-heading"><i class="fa fa-binoculars" aria-hidden="true">角色信息</i>
                        {% if user_id %}
                            <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 %}
                    </div>
                    <div class="panel panel-body" style="color: #737373">
                        提示:点击用户后才能为其分配角色
                    </div>
                    <table class="table table-condensed">
                        <thead>
                        <tr>
                            <th>角色</th>
                            <th>选项</th>
                        </tr>
                        </thead>
                        <tbody>
                        {% for role in all_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 {% if role.id     in user_has_role_dict %}checked{% endif %}
                                           type="checkbox" name="roles" value="{{ role.id }}">
                                </td>
                            </tr>
                        {% endfor %}
                        </tbody>
                    </table>
                </form>
            </div>
        </div>


        <div class="col-md-6 permission-area">
            <div class="panel panel-default">
                <form method="post">
                    {% csrf_token %}
                    <input type="hidden" name="type" value="permission">
                    <div class="panel-heading"><i class="fa fa-binoculars" aria-hidden="true">权限分配</i>
                        {% if role_id %}
                            <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 %}
                    </div>
                    <div class="panel panel-body">
                        提示:必须要选择角色,才可以分配权限
                    </div>
                    <table class="table">
                        <tbody>
                        {% for item in all_menu_queryset %}
                            <tr class="root">
                                <td>
                                    <i class="fa fa-caret-down" aria-hidden="true"></i>
                                    {{ item.title }}
                                    <div class="select-help">
                                        <div class="check-all">
                                            <label for="check_all_{{ item.mid }}">全选</label>
                                            <input id="check_all_{{ item.mid }}" type="checkbox">
                                        </div>
                                    </div>
                                </td>
                            </tr>
                            {% if item.children %}
                                <tr class="node">
                                    <td>
                                        {% for node in item.children %}
                                            <div class="parent">
                                                <input id="permission_{{ node.id }}" name="permissions"
                                                       {% if node.id in user_has_permissions_dict %}checked{% endif %}
                                                       value="{{ node.id }}" type="checkbox">
                                                <label for="permission_{{ node.id }}">{{ node.title }}(菜单)</label>
                                            </div>
                                            <div class="children">
                                                {% for child in node.children %}
                                                    <div class="child">

                                                        <input id="permission_{{ child.id }}" name="permissions"
                                                               {% if child.id in user_has_permissions_dict %}checked{% endif %}
                                                               type="checkbox" value="{{ child.id }}">

                                                        <label for="permission_{{ child.id }}">{{ child.title }}</label>
                                                    </div>
                                                {% endfor %}
                                            </div>
                                        {% endfor %}
                                    </td>
                                </tr>
                            {% endif %}
                        {% endfor %}
                        </tbody>
                    </table>
                </form>
            </div>
        </div>
    </div>
{% endblock %}

{% block js %}
    <script type="text/javascript">
    $(function () {
        $(".check-all input:checkbox").change(function () {
            $(this).parents(".root").next().find("input:checkbox").prop("checked", $(this).prop("checked"));
        })
    })
    </script>
{% endblock %}
templates

猜你喜欢

转载自www.cnblogs.com/chengege/p/10727213.html