權限分配實現思路


先上一張,效果圖。 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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM