權限管理——版本3

權限管理——版本3

1.目標

  -解決版本的BUG,即,當咱們點擊添加/刪除/編輯時,菜單的首頁都會縮小,按理說:不該該縮小。css

  -看看最終的實現:html

    

    點擊添加以後,注意看左邊的菜單管理,按理是不該該縮小的,可是以前的版本2是會縮小的,因此須要解決這個問題。jquery

    

    

解決方案思路:數據庫

  

解決:
        1.找到當前點擊進入的url,找到這個url的組,讓這個組默認選中菜單就能夠。
            - 請求url:request.path_info
            - 全部的url; .....  
            -以上兩個一一匹配,成功以後,找到組id,經過組id找到當前組裏的"is_menu"=True的這條記錄,
            在它後面加個active = True爲默認被選中。而後須要再一次循環,把is_menu爲True取出來,讓這兩生成菜單就能夠了。
            前提:一組一個菜單
            
        2.修改數據庫的記錄。
            1.方法1:在權限表加一個組內菜單的字段,自關聯。null 就爲菜單
                /userinfo/      list     null     組1
                /userinfo/add     add     1          組1
                /userinfo/edit     edit     1          組1
                /userinfo/del     del     1          組1
                
                /order/            list    null    組2
                /order/add        add        5        組2
                /order/edit        edit    5        組2
                /order/del        del        5        組2
                
            2.方法2:
                設一個菜單字典:
                    menu_dict = {
                        1:{'id':1,'title':'用戶列表','url':'/userinfo/','menu_gp_id':None,'menu_id':1,'menu_title':'菜單管理',active=True}
                        5:{'id':5,'title':'訂單列表','url':'/order/','menu_gp_id':None,'menu_id':2,'menu_title':'訂單管理'}
                    }
                
                    current_url = request.path_info
                    for item in menu_list:
                        url = item['url']
                        regex = '^{0}$'format(url)
                        if re.match(regex,current_url):
                            menu_gp_id = item['menu_gp_id']
                            if not menu_gp_id:
                                #給本身加active = True,下面兩個方式均可以用,由於用的是同一個引用。
                                    item['active'] = True
                                    menu_dict[item]['id']['active']=True
                            else:
                                menu_dict[menu_gp_id]['active'] = True

 

 

2.代碼

app01/views.py:django

import re

from django.shortcuts import render,redirect,HttpResponse
from django.conf import settings
from rbac import models
from rbac.service.init_permission import init_permission
def login(request):
    if request.method == "GET":
        return render(request,'login.html')
    else:
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        user = models.User.objects.filter(username=user,password=pwd).first()
        print(request.POST)
        if not user:
            return render(request, 'login.html')
        init_permission(user,request)
        return redirect('/index/')


def index(request):

    return HttpResponse('歡迎登陸')


class BasePagePermission(object):
    def __init__(self,code_list):
        self.code_list = code_list

    def has_add(self):
        if "add" in self.code_list:
            return True

    def has_edit(self):
        if 'edit' in self.code_list:
            return True
    def has_del(self):
        if 'del' in self.code_list:
            return True

def userinfo(request):
    page_permission = BasePagePermission(request.permission_code_list)
    data_list = [
        {'id':1,'name':'xxx1'},
        {'id':2,'name':'xxx2'},
        {'id':3,'name':'xxx3'},
        {'id':4,'name':'xxx4'},
        {'id':5,'name':'xxx5'},
    ]

    return render(request,'userinfo.html',{'data_list':data_list,'page_permission':page_permission})


def userinfo_add(request):
    page_permission = BasePagePermission(request.permission_code_list)
    return render(request, 'userinfo_add.html', { 'page_permission': page_permission})



class OrderPagePermission(BasePagePermission):

    def has_report(self):
        if 'report' in self.code_list:
            return True

def order(request):
    order_permission = OrderPagePermission(request.permission_code_list)


    return render(request,'order.html')

def order_add(request):
    return HttpResponse('添加訂單頁面')
View Code

 

settings.py:session

 

 

urls.py:app

from django.conf.urls import url
from django.contrib import admin
from rbac import views
from app01 import views as app01_views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^test/', views.test),
url(r'^login/', app01_views.login),
url(r'^index/', app01_views.index),
url(r'^userinfo/$', app01_views.userinfo),
url(r'^userinfo/add/$', app01_views.userinfo_add),
url(r'^order/$', app01_views.order),
url(r'^order/add/$', app01_views.order_add),
]

 

 rbac\middlewares\rbac.py:ide

import re

from django.shortcuts import redirect,HttpResponse
from django.conf import settings

class MiddlewareMixin(object):
    def __init__(self, get_response=None):
        self.get_response = get_response
        super(MiddlewareMixin, self).__init__()

    def __call__(self, request):
        response = None
        if hasattr(self, 'process_request'):
            response = self.process_request(request)
        if not response:
            response = self.get_response(request)
        if hasattr(self, 'process_response'):
            response = self.process_response(request, response)
        return response


class RbacMiddleware(MiddlewareMixin):

    def process_request(self,request):
        # 1. 獲取當前請求的URL
        # request.path_info
        # 2. 獲取Session中保存當前用戶的權限
        # request.session.get("permission_url_list')
        current_url = request.path_info

        # 當前請求不須要執行權限驗證
        for url in settings.VALID_URL:
            if re.match(url,current_url):
                return None

        permission_dict = request.session.get(settings.PERMISSION_URL_DICT_KEY)
        if not permission_dict:
            return redirect('/login/')

        flag = False
        for group_id,code_url in permission_dict.items():

            for db_url in code_url['urls']:
                regax = "^{0}$".format(db_url)
                if re.match(regax, current_url):
                    request.permission_code_list = code_url['codes']
                    flag = True
                    break
            if flag:
                break

        if not flag:
            return HttpResponse('無權訪問')
View Code

 

rbac\service\init_permission.pyui

from django.conf import settings


def init_permission(user,request):
    """
    初始化權限信息,獲取權限信息並放置到session中。
    :param user:
    :param request:
    :return:
    """
    permission_list = user.roles.values('permissions__id',
                                        'permissions__title',              # 用戶列表
                                        'permissions__url',
                                        'permissions__code',
                                        'permissions__menu_gp_id',         # 組內菜單ID,Null表示是菜單
                                        'permissions__group_id',
                                        'permissions__group__menu_id',     # 菜單ID
                                        'permissions__group__menu__title',#  菜單名稱
                                        ).distinct()

    # 菜單相關(之後再匹配)
    sub_permission_list = []
    for item in permission_list:
        tpl = {
            'id':item['permissions__id'],
            'title':item['permissions__title'],
            'url':item['permissions__url'],
            'menu_gp_id':item['permissions__menu_gp_id'],
            'menu_id':item['permissions__group__menu_id'],
            'menu_title':item['permissions__group__menu__title'],
        }
        sub_permission_list.append(tpl)
    request.session[settings.PERMISSION_MENU_KEY] = sub_permission_list

    # 權限相關
    result = {}
    for item in  permission_list:
        group_id = item['permissions__group_id']
        code = item['permissions__code']
        url = item['permissions__url']
        if group_id in result:
            result[group_id]['codes'].append(code)
            result[group_id]['urls'].append(url)
        else:
            result[group_id] = {
                'codes':[code,],
                'urls':[url,]
            }

    request.session[settings.PERMISSION_URL_DICT_KEY] = result
View Code

 

 rbac.cssthis

.item-permission{
    padding: 3px 10px;
}
.item-permission a{
    display: block;
}
.item-permission a.active{
    color: red;
}
.hide{
    display: none;
}

 

rbac.js

/**
 * Created by Administrator on 2017/11/8.
 */
 $(function () {
    $('.item-title').click(function () {
        if($(this).next().hasClass('hide')){
            $(this).next().removeClass('hide')
        }else{
            $(this).next().addClass('hide')
        }
    })


});

 

rbac\templatetags\rbac.py

import re
from django.template import Library
from django.conf import settings
register = Library()

@register.inclusion_tag("xxxxx.html")
def menu_html(request):
    """
    去Session中獲取菜單相關信息,匹配當前URL,生成菜單
    :param request:
    :return:
    """
    menu_list = request.session[settings.PERMISSION_MENU_KEY]
    current_url = request.path_info

    menu_dict = {}
    for item in menu_list:
        if not item['menu_gp_id']:
            menu_dict[item['id']] = item

    for item in menu_list:
        regex = "^{0}$".format(item['url'])
        if re.match(regex,current_url):
            menu_gp_id = item['menu_gp_id']
            if menu_gp_id:
                menu_dict[menu_gp_id]['active'] = True
            else:
                menu_dict[item['id']]['active'] = True

    result = {}
    for item in menu_dict.values():
        active = item.get('active')
        menu_id = item['menu_id']
        if menu_id in result:
            result[menu_id]['children'].append({ 'title': item['title'], 'url': item['url'],'active':active})
            if active:
                result[menu_id]['active'] = True
        else:
            result[menu_id] = {
                'menu_id':item['menu_id'],
                'menu_title':item['menu_title'],
                'active':active,
                'children':[
                    { 'title': item['title'], 'url': item['url'],'active':active}
                ]
            }

    return {'menu_dict':result}
View Code

 

rbac\models.py

from django.db import models

class Menu(models.Model):
    """
    菜單組
    """
    title = models.CharField(max_length=32)


class Group(models.Model):
    """
    權限組
    """
    caption = models.CharField(verbose_name='組名稱',max_length=16)
    menu = models.ForeignKey(verbose_name='所屬菜單',to='Menu',default=1)


class Permission(models.Model):
    """
    權限表
    """
    title = models.CharField(verbose_name='標題',max_length=32)
    url = models.CharField(verbose_name="含正則URL",max_length=64)

    menu_gp = models.ForeignKey(verbose_name='組內菜單',to='Permission',null=True,blank=True,related_name='x1')

    code = models.CharField(verbose_name="代碼",max_length=16)
    group = models.ForeignKey(verbose_name='所屬組',to="Group")

    class Meta:
        verbose_name_plural = "權限表"

    def __str__(self):
        return self.title

class User(models.Model):
    """
    用戶表
    """
    username = models.CharField(verbose_name='用戶名',max_length=32)
    password = models.CharField(verbose_name='密碼',max_length=64)
    email = models.CharField(verbose_name='郵箱',max_length=32)

    roles = models.ManyToManyField(verbose_name='具備的全部角色',to="Role",blank=True)

    class Meta:
        verbose_name_plural = "用戶表"

    def __str__(self):
        return self.username

class Role(models.Model):
    """
    角色表
    """
    title = models.CharField(max_length=32)
    permissions = models.ManyToManyField(verbose_name='具備的全部權限',to='Permission',blank=True)
    class Meta:
        verbose_name_plural = "角色表"

    def __str__(self):
        return self.title
View Code

 

layout.html:

{% load rbac %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="/static/rbac/rbac.css" />
    <title>Title</title>
</head>
<body>
        <div style="float: left;width: 20%;height: 500px;background-color: #dddddd">
            {% menu_html request %}
        </div>
        <div style="float: left;width: 80%">
            {% block content %}{% endblock %}
        </div>

            <script src="/static/jquery-3.2.1.min.js"></script>
            <script src="/static/rbac/rbac.js"></script>

</body>
</html>
View Code

 

xxxxx.html:

{% for k,item in menu_dict.items %}
    <div class="item">
        <div class="item-title">{{ item.menu_title }}</div>
        {% if item.active %}
            <div class="item-permission">
        {% else %}
            <div class="item-permission hide">
        {% endif %}
            {% for v in item.children %}

                {% if v.active %}
                    <a href="{{ v.url }}" class="active">{{ v.title }}</a>
                {% else %}
                    <a href="{{ v.url }}">{{ v.title }}</a>
                {% endif %}

            {% endfor %}
        </div>
    </div>
{% endfor %}
View Code
相關文章
相關標籤/搜索