權限管理——版本2

權限管理——版本2 

1.完成目標

 菜單相關:
    [
        {'menu_id':1,'menu_title':'菜單1','title':'用戶列表','url':'/userinfo/'},
        {'menu_id':1,'menu_title':'菜單1','title':'訂單列表','url':'/order/'},
        {'menu_id':2,'menu_title':'菜單2','title':'xxx列表','url':'/xxx/'},
        {'menu_id':3,'menu_title':'菜單2','title':'aaa列表','url':'/aaa/'},
    ]

    菜單1
        用戶管理

    菜單2
        訂單管理

    分級,默認展開選中。

    構建數據結構:
        {
            1: {
                    'menu_id': 1,
                    'menu_title': '菜單一',
                    'active': None,
                    'children': [
                            {'title': '訂單列表', 'url': '/order/', 'active': None}
                        ]
                    }
            2: {
                'menu_id': 2,
                'menu_title': '菜單二',
                'active': True,
                'children': [
                        {'title': '用戶列表', 'url': '/userinfo/', 'active': True}
                    ]
                },

        }
    小結:  菜單相關的數據結構,還須要和當前請求的url匹配,匹配成功,actice爲True。
            active有兩個操做: 1.目標是否變紅   2.目標是否展開或縮小。

 

5.從構建數據結構傳過來的數據格式變了: 作了一個settings配置名,改如下就不須要每一個地方都改。
6.循環數據,拿字典裏面的key,value,字典套字典,要學會取值。
7.爲了讓視圖知道codes,咱們還須要取codes。
8.把生成菜單的標籤放到simple_tag裏load就能夠了
9.擴展一個inclusion_tag自定義頁面的功能,後面只須要跟一個頁面。css

 

結果實例圖:html

  

 

 

2.代碼

1.app01/views.pydjango

from django.shortcuts import render,redirect,HttpResponse
from rbac import models
from rbac.service.init_permission import init_permission
from django.conf import settings
import re


def login(reqeust):
    if reqeust.method == 'GET':
        return  render(reqeust,'login.html')
    else:
        user = reqeust.POST.get('user')
        pwd = reqeust.POST.get('pwd')
        print(reqeust.POST)
        user = models.User.objects.filter(username=user,password=pwd).first()
        print(user)
        if not user:
            return render(reqeust,'login.html')
        init_permission(user,reqeust)
        print(111)
        return redirect('/index/')


def index(request):
    print(222)
    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):
    print(request.permisstion_code_list)
    page_permission = BasePagePermission(request.permisstion_code_list)
    data_list = [
        {'id':1,'name':'xxx1'},
        {'id':2,'name':'xxx2'},
        {'id':3,'name':'xxx3'},
        {'id':4,'name':'xxx4'},
        {'id':5,'name':'xxx5'},
    ]

    menu_list = request.session[settings.PERMISSTION_MENU_KEY]

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




def userinfo_add(request):
    page_permission = BasePagePermission(request.permisstion_code_list)
    return HttpResponse('添加用戶頁面')


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


def order(request):
    order_permission = OrderPagePermission(request.permisstion_code_list)
    return render(request, 'order.html')
views.py

 

2.settings:session

STATIC_URL = '/static/'

PERMISSTION_URL_DICT = 'permissions_url_dict'
PERMISSTION_MENU_KEY = 'asdasdasdada'
VALID_URL = [
    '/login/',
    '/admin.*/'

]

 

3.urls.py數據結構

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)


]

 

4.rbac/middlewares/rbac.pyapp

import re
from permission import settings

from django.shortcuts import redirect,HttpResponse


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().不能request.session[],由於可能沒數據。
           3.設置白名單,獲取到白名單的放行數據,和用戶所擁有的權限url,匹配。 若是匹配,就不須要通過權限的檢查。
           4.當用戶訪問了組的列表頁面後,就應該知道他在這個組裏還有什麼權限。
                -1.分組: 1能夠是用戶組, 2是訂單組
                -2.不當是用戶列表頁面須要知道他的全部權限,其它頁面也應該知道。使用codes來獲取。
                -3. 以上這樣設置,無論什麼頁面都能知道全部的權限url,找到codes就能夠。
                        list = {
                        1:{
                            'codes':['list','add','edit','del']
                            'urls':[
                            /userinfo/
                            /userinfo/add/
                            /userinfo/edit/(\d+)/
                            /userinfo/del/(\d+)/
                            ]
                        }
                    }
            5.從構建數據結構傳過來的數據格式變了: 作了一個settings配置名,改如下就不須要每一個地方都改。
            6.循環數據,拿字典裏面的key,value,字典套字典,要學會取值。
            7.爲了讓視圖知道codes,咱們還須要取codes。
            8.把生成菜單的標籤放到simple_tag裏load就能夠了
            9.擴展一個inclusion_tag自定義頁面的後面只須要跟一個頁面。
             '''
        current_url = request.path_info
        
        for url in settings.VALID_URL:
            if re.match(url,current_url):
                print(url,current_url)
                return None


        permission_dict = request.session.get(settings.PERMISSTION_URL_DICT)  # 拿到url格式的數據
        if not permission_dict:
            return redirect('/login/')
        flag = False
        for group_id,code_url in permission_dict.items():  # 用in不行,含正則的url使用in會匹配不了,所要要用正則:re.match
            for db_url  in code_url['urls']:
                regax =  '^{0}$'.format(db_url) #加上起止符,絕對匹配。
                if re.match(regax, current_url):  # 若是匹配成功,就已等
                    request.permisstion_code_list = code_url['codes']   #取到codes列表,存到request裏
                    flag = True
                    break
            if flag:
                break
        if not flag:
            return HttpResponse('無權訪問')
rbac.py

 

5.rbac/service/init_permission.pyide

from django.conf import  settings

def init_permission(user,request):
    '''
    初始化權限信息,把權限url放到session。
    :param user:
    :param request:
    :return:

    list = {
    1:{
        'codes':['list','add','edit','del']
        'urls':[
        /userinfo/
        /userinfo/add/
        /userinfo/edit/(\d+)/
        /userinfo/del/(\d+)/
        ]
    }
}

    菜單相關:
    [
        {'menu_id':1,'menu_title':'菜單1','title':'用戶列表','url':'/userinfo/'},
        {'menu_id':1,'menu_title':'菜單1','title':'訂單列表','url':'/order/'},
        {'menu_id':2,'menu_title':'菜單2','title':'xxx列表','url':'/xxx/'},
        {'menu_id':3,'menu_title':'菜單2','title':'aaa列表','url':'/aaa/'},
    ]

    菜單1
        用戶管理

    菜單2
        訂單管理

    分級,默認展開選中。

    構建數據結構:
        {
            1: {
                    'menu_id': 1,
                    'menu_title': '菜單一',
                    'active': None,
                    'children': [
                            {'title': '訂單列表', 'url': '/order/', 'active': None}
                        ]
                    }
            2: {
                'menu_id': 2,
                'menu_title': '菜單二',
                'active': True,
                'children': [
                        {'title': '用戶列表', 'url': '/userinfo/', 'active': True}
                    ]
                },

        }
    小結:  菜單相關的數據結構,還須要和當前請求的url匹配,匹配成功,actice爲True。
            active有兩個操做: 1.目標是否變紅   2.目標是否展開或縮小。
    '''
    permission_list2 = user.roles.values('permissions__title', #權限名稱
                                         'permissions__url',   #權限url
                                         'permissions__is_menu', #權限是不是菜單
                                         'permissions__codes',  #權限的codes
                                         'permissions__group_id',   #組id
                                         'permissions__group__menu_id', #菜單id
                                         'permissions__group__menu__title' #菜單名稱
                                         ).distinct()
    menu_list = []
    #去掉不是菜單的url
    for item in permission_list2:
        if not item['permissions__is_menu']:
            continue
        tpl = {
            'menu_id':item['permissions__group__menu_id'],
            'menu_title':item['permissions__group__menu__title'],
            'title':item['permissions__title'],
            'url':item['permissions__url'],
            'active':False
        }
        menu_list.append(tpl)
    request.session[settings.PERMISSTION_MENU_KEY] = menu_list


    #權限相關
    result = {}
    for item in  permission_list2:
        group_id = item['permissions__group_id']
        code = item['permissions__codes']
        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.PERMISSTION_URL_DICT] = result

    #拿到用戶請求url,和session作對比,若是在,可訪問,不在,一邊去。
View Code

 

6.rbac/static/rabc/rbac.cssthis

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

 

7..rbac/static/rabc/rbac.jsurl

/**
 * 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')
        }
    })


});

 

8.rbac/templatetags/rbac.pyspa

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.PERMISSTION_MENU_KEY]
    current_url = request.path_info
    result = {}
    for item in menu_list:
        url = item['url']
        print(url)
        regex = '^{0}$'.format(url)
        active = False
        if re.match(regex,current_url):
            active = True
        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':menu_id,
                'menu_title':item['menu_title'],
                'active': active,
                'children': [
                    {'title': item['title'], 'url': item['url'], 'active': active},
                ]
            }
    return {'menu_dict':result}
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
        
View Code

 

9.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 %}
相關文章
相關標籤/搜索