django之权限管理公共组件

公共组件使用

公共组件的基本搭建

在上一篇已经是学习如何搭建一个公共组件,可以拷贝到任何项目里面,实现权限的管理工作,今天再次学习下公共组件的使用

  • 新建一个项目,并把公共组件拷贝到新项目中取,并且在setting中注册组件
  • 中间件的注册

公共组件的配置管理

在中间件中,通过导入项目的setting文件,从里面导入变量信息,所以我们在setting里面设置了如下变量信息:

# ############################## RBAC权限相关配置开始 ##############################
# # 无需权限控制的URL
RBAC_NO_AUTH_URL = [
    ‘/login.html‘,
    ‘/index.html‘,
    ‘/register.html‘,
    ‘/admin.*‘,
    ‘/rbac.*‘,
]

# session中保存权限信息的Key
RBAC_PERMISSION_SESSION_KEY = "rbac_permission_session_key"

# Http请求中传入的参数,根据其获取GET、POST、EDIT等检测用户是否具有相应权限
# 例如:
#       http://www.example.com?md=get   表示获取
#       http://www.example.com?md=post  表示添加
#       http://www.example.com?md=del   表示删除
RBAC_QUERY_KEY = "md"
RBAC_DEFAULT_QUERY_VALUE = "look"

# 无权访问时,页面提示信息
RBAC_PERMISSION_MSG = "无权限访问"

# Session中保存菜单和权限信息的Key
RBAC_MENU_PERMISSION_SESSION_KEY = "rbac_menu_permission_session_key"
RBAC_MENU_KEY = "rbac_menu_key"
RBAC_MENU_PERMISSION_KEY = "rbac_menu_permission_key"

# 菜单主题
RBAC_THEME = "default"
# ############################## RBAC权限相关配置结束 ##############################

公共组件的使用

程序如果使用的话,是需要先登陆的,RBAC_NO_AUTH_URL这个里面设置了登陆的白名单。下面第一步先设置一个登陆页面

  • 登陆页面
    templates下面新建一个login.html页面
  • 创建url
  • 创建login函数
  • 创建用户表
    这个用户表 是在新的app下面创建的,这里是webapp。所以要在web这个app下面的modles里面创建这个表去,如下:
  • 优化完成上面的login函数
    上面创建完表后,我们可以在login函数里面,来验证输入的用户的正确性,通过对用户的验证,来获取当前用户的权限,菜单,已经session中的值
    
    from django.shortcuts import render,HttpResponse,redirect
    from web import models
    def login(request):
    if request.method == "GET":
        return render(request,‘login.html‘)
    else:
        u = request.POST.get(‘username‘)
        p = request.POST.get(‘password‘)
        obj = models.UserInfo.objects.filter(user__username=u,user__password=p).first()#当前用户的对象这个对象里面有obj.id ,obj_nickname,obj.user_id
        if obj:
            #获取当前用户的权限
            #获取当前用户的菜单
            #去配置文件中获取key,写入session中
            from rbac.service import initial_permission
            initial_permission(request,obj.user_id)
            #也可以自定义session
            request.session[‘user_info‘] = {‘username‘:u,‘nickname‘:obj.nickname,‘uid‘:obj.id}
            return  redirect(‘/bgindex.html‘)
        else:
            return render(request,‘login.html‘)

>上面导入了一个模块,这service.py模块中封装了权限和菜单,其中的代码如下:

#!/usr/bin/env python

-- coding:utf-8 --

import re
from django.conf import settings

from . import models

def initial_permission(request, user_id):
"""
初始化权限,获取当前用户权限并添加到session中
将当前用户权限信息转换为以下格式,并将其添加到Session中
{
‘/index.html‘: [‘GET‘,‘POST‘,‘DEL‘,‘EDIT],
‘/detail-(\d+).html‘: [‘GET‘,‘POST‘,‘DEL‘,‘EDIT],
}

:param request: 请求对象
:param user_id: 当前用户id
:return:
"""

"""初始化权限信息"""
roles = models.Role.objects.filter(users__user_id=user_id)

p2a = models.Permission2Action2Role.objects.filter(role__in=roles).values(‘permission__url‘,
                                                                          "action__code").distinct()
user_permission_dict = {}
for item in p2a:
    if item[‘permission__url‘] in user_permission_dict:
        user_permission_dict[item[‘permission__url‘]].append(item[‘action__code‘])
    else:
        user_permission_dict[item[‘permission__url‘]] = [item[‘action__code‘], ]

request.session[settings.RBAC_PERMISSION_SESSION_KEY] = user_permission_dict

"""初始化菜单信息,将菜单信息和权限信息添加到session中"""
menu_list = list(models.Menu.objects.values(‘id‘, ‘caption‘, ‘parent_id‘))

menu_permission_list = list(models.Permission2Action2Role.objects.filter(role__in=roles,
                                                                    permission__menu__isnull=False).values(
    ‘permission_id‘,
    ‘permission__url‘,
    ‘permission__caption‘,
    ‘permission__menu_id‘).distinct())
request.session[settings.RBAC_MENU_PERMISSION_SESSION_KEY] = {
    settings.RBAC_MENU_KEY: menu_list,
    settings.RBAC_MENU_PERMISSION_KEY: menu_permission_list
}

def fetch_permission_code(request, url):
"""
根据URL获取该URL拥有的权限,如:["GET","POST"]
:param request:
:param url:
:return:
"""
user_permission_dict = request.session.get(settings.RBAC_PERMISSION_SESSION_KEY)
if not user_permission_dict:
return []
for pattern, code_list in user_permission_dict.items():
if re.match(pattern, url):
return code_list
return []

- ** bgindex**页面搭建
bgindex是后台的管理页面,这个页面是根据登陆用户的权限来显示对应的内容。这里是走中间件了,所以中间件会执行筛查的工作,中间件中的代码如下:

#!/usr/bin/env python

-- coding:utf-8 --

import re
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class RbacMiddleware(MiddlewareMixin):
def process_request(self, request, *args, **kwargs):
"""
检查用户是否具有权限访问当前URL
:param request:
:param args:
:param kwargs:
:return:
"""

    """跳过无需权限访问的URL"""
    for pattern in settings.RBAC_NO_AUTH_URL:
        if re.match(pattern, request.path_info):
            return None

    """获取当前用户session中的权限信息"""
    permission_dict = request.session.get(settings.RBAC_PERMISSION_SESSION_KEY)
    if not permission_dict:
        return HttpResponse(settings.RBAC_PERMISSION_MSG)

    """当前URL和session中的权限进行匹配"""

    flag = False
    for pattern, code_list in permission_dict.items():
        upper_code_list = [item.upper() for item in code_list]
        if re.match(pattern, request.path_info):
            request_permission_code = request.GET.get(settings.RBAC_QUERY_KEY, settings.RBAC_DEFAULT_QUERY_VALUE).upper()
            if request_permission_code in upper_code_list:
                request.permission_code = request_permission_code
                request.permission_code_list = upper_code_list
                flag = True
                break

    if not flag:
        return HttpResponse(settings.RBAC_PERMISSION_MSG)

通过中间件的筛查后,我们可以得到值,然后对值进行判断来操作,如下:

    上面是FBV模式,我们也可以做成CBV模式如下:
    dispatch是这样的工作模式:
    ![](http://i2.51cto.com/images/blog/201805/17/d3b613c271249192498f222e6980b84f.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
    我们自己写一个,让dispatch自己走咱们自己写的规则,多继承,会执行前面的继承,前面执行了,后面的里面的dispatch就不会执行
    ![](http://i2.51cto.com/images/blog/201805/17/1c5ddfdb763e7cbd45c710aa2248f5a8.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)

![](http://i2.51cto.com/images/blog/201805/17/d429cda4c38f86fb3276e2ec04b266ed.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)

报障单应用

首先在web的数据库里面创建表

from django.db import models
from rbac.models import User as RbacUser
import datetime
class UserInfo(models.Model):
    nickname = models.CharField(max_length=16)
    user = models.OneToOneField(RbacUser,on_delete=models.CASCADE)
    def __str__(self):
        return self.nickname

class Order(models.Model):
    """
    保障单
    """
    title = models.CharField(max_length=32,verbose_name=‘保障标题‘)
    detail = models.TextField(verbose_name=‘保障详细信息‘)
    create_user = models.ForeignKey(UserInfo,related_name=‘aaa‘,on_delete=models.CASCADE)
    ctime = models.DateTimeField(verbose_name=‘创建时间‘)
    status_choice=(
        (1,‘未处理‘),
        (2,‘处理中‘),
        (3,‘已处理‘)
    )
    status = models.IntegerField(choices=status_choice,default=1)
    processor = models.ForeignKey(UserInfo,related_name=‘bbb‘,null=True,blank=True,on_delete=models.CASCADE)
    solution = models.TextField(null=True,blank=True)
    ptime = models.DateTimeField(null=True,blank=True)
    def __str__(self):
        return self.title

然后在setting里面注册web,
注册成功后,生成数据库表

>python3 manage.py makemigrations
>python3 manage.py migrate

通过admin 来后台添加数据

数据的添加-------------------------------------------

创建函数bgindex

创建bgindex 页面

下面是simple_tag 代码:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
import os
from django import template
from django.utils.safestring import mark_safe
from django.conf import settings

register = template.Library()

def process_menu_tree_data(request):
    """
    根据Session中获取的菜单以及权限信息,结构化数据,生成特殊数据结构,如:
    [
        {id:1,caption:‘菜单标题‘,parent_id:None,status:False,opened:False,child:[...]},
    ]
    PS: 最后一层的权限会有url,即:菜单跳转的地址

    :param request:
    :return:
    """
    menu_permission_dict = request.session.get(settings.RBAC_MENU_PERMISSION_SESSION_KEY)
    if not menu_permission_dict:
        raise Exception(‘Session中未保存当前用户菜单以及权限信息,请登录后初始化权限信息!‘)

    """ session中获取菜单和权限信息 """
    all_menu_list = menu_permission_dict[settings.RBAC_MENU_KEY]
    menu_permission_list = menu_permission_dict[settings.RBAC_MENU_PERMISSION_KEY]

    all_menu_dict = {}
    for row in all_menu_list:
        row[‘opened‘] = False
        row[‘status‘] = False
        row[‘child‘] = []
        all_menu_dict[row[‘id‘]] = row

    """ 将权限信息挂靠在菜单上,并设置是否默认打开,以及默认显示 """
    for per in menu_permission_list:

        item = {‘id‘: per[‘permission_id‘], ‘caption‘: per[‘permission__caption‘], ‘url‘: per[‘permission__url‘],
                ‘parent_id‘: per[‘permission__menu_id‘],
                ‘opened‘: False,
                ‘status‘: True}
        menu_id = item[‘parent_id‘]
        all_menu_dict[menu_id][‘child‘].append(item)

        # 将当前URL和权限正则进行匹配,用于指示是否默认打开菜单
        if re.match(item[‘url‘], request.path_info):
            item[‘opened‘] = True

        if item[‘opened‘]:
            pid = menu_id
            while not all_menu_dict[pid][‘opened‘]:
                all_menu_dict[pid][‘opened‘] = True
                pid = all_menu_dict[pid][‘parent_id‘]
                if not pid:
                    break

        if item[‘status‘]:
            pid = menu_id
            while not all_menu_dict[pid][‘status‘]:
                all_menu_dict[pid][‘status‘] = True
                pid = all_menu_dict[pid][‘parent_id‘]
                if not pid:
                    break

    result = []
    for row in all_menu_list:
        pid = row[‘parent_id‘]
        if pid:
            all_menu_dict[pid][‘child‘].append(row)
        else:
            result.append(row)

    return result

def build_menu_tree_html(menu_list):
    tpl1 = """
        <div class=‘rbac-menu-item‘>
            <div class=‘rbac-menu-header‘>{0}</div>
            <div class=‘rbac-menu-body {2}‘>{1}</div>
        </div>
    """
    tpl2 = """
        <a href=‘{0}‘ class=‘{1}‘>{2}</a>
    """
    menu_str = ""
    for menu in menu_list:
        if not menu[‘status‘]:
            continue

        if menu.get(‘url‘):
            menu_str += tpl2.format(menu[‘url‘], "" if menu[‘opened‘] else ‘rbac-active‘, menu[‘caption‘])
        else:
            if menu.get(‘child‘):
                child = build_menu_tree_html(menu.get(‘child‘))
            else:
                child = ""
            menu_str += tpl1.format(menu[‘caption‘], child, "" if menu[‘opened‘] else ‘rbac-hide‘)
    return menu_str

@register.simple_tag
def rbac_menu(request):
    """
    根据Session中当前用户的菜单信息以及当前URL生成菜单
    :param request: 请求对象
    :return:
    """
    menu_tree_list = process_menu_tree_data(request)
    return mark_safe(build_menu_tree_html(menu_tree_list))

@register.simple_tag
def rbac_css():
    file_path = os.path.join(‘rbac‘, ‘theme‘, settings.RBAC_THEME, ‘rbac.css‘)
    if os.path.exists(file_path):
        return mark_safe(open(file_path, ‘r‘, encoding=‘utf-8‘).read())
    else:
        raise Exception(‘rbac主题CSS文件不存在‘)

@register.simple_tag
def rbac_js():
    file_path = os.path.join(‘rbac‘, ‘theme‘, settings.RBAC_THEME, ‘rbac.js‘)
    if os.path.exists(file_path):
        return mark_safe(open(file_path, ‘r‘, encoding=‘utf-8‘).read())
    else:
        raise Exception(‘rbac主题JavaScript文件不存在‘)

css 和js 通过simple_tag 应用

保障单

当点击保障单的时候,会跳转到新的保障单的页面,
但是这里要带参数url md的方法,上面代码 我们在中间件里面的默认值是GET,我们可以通过设置配置文件和中间件来修改默认值
配置文件修改:

中间件修改

trouble函数代码

当点击了保障单后,跳转到新的url,这里需要创建新的url路由。

新的页面通过模板语言,导入来实现格式

在后台给order表添加数据后,前端访问会出现数据

添加按钮

编辑详细信息

删除

添加



数据库时间自动添加

原文地址:http://blog.51cto.com/sgk2011/2117612

时间: 2024-10-07 07:10:41

django之权限管理公共组件的相关文章

Django之权限管理

Django权限管理之初步完整版 项目背景:这是一个权限管理系统(给一些角色和他们的权限指URL和页面可以删除的按钮比如:增删改查) 使用到了中间件,和初始化权限,使用了admin的后台管理系统. 我们这个是基于角色的权限访问控制(Role-Based Access Control)做一个组件. 首先建立一个项目工程里面有另个应用:app01与rbac, 我们在rbac中model中建立一些数据类型代码如下: from django.db import models # Create your

Django之权限管理插件

参考:https://www.cnblogs.com/alex3714/articles/6661911.html http://www.cnblogs.com/wupeiqi/articles/6229414.html 1.      什么是权限? 权限就是对软件系统中各种资源的访问和操作的控制! 2.      什么是资源? 在软件系统中,数据库.内存.硬盘里数据都是资源,资源就是数据! 3.      动作 资源本身是静态的,必须通过合适的动作对其进行访问和操作,我们说要控制权限,其实本质

iOS 使用CocoaPods管理私有库的公共组件

最近要使用私有公共组件,故,有了如下的故事. 参考地址: http://www.cocoachina.com/ios/20150228/11206.html 本文使用 https://coding.net 作为Git私有库地址.步骤如下: 1. 创建一个私有的Git 仓库.(例如:SKPodsStart,创建后地址:https://git.coding.net/LeouCC/SKPodsStart.git 2. 添加一个私有Spec Repo到本地,终端命令如下:pod repo add [Sp

django 自定义user使用权限管理模块

这篇文章主要是讲如何让自定义的user模块也能用到django.contrib.auth中的权限管理模块 看这篇文章之前请先看一下我前边的两篇文章,本文以这两篇文章为基础: django 自定义 USER 用源码告诉你django权限管理是怎么回事 下边是一个大概的实现,后边再做详细分析: 1.user model自定义 class AbstractUser(models.Model): # 登录信息 id = models.AutoField(primary_key=True) staff =

2.4、使用Django自带的admin用户管理,权限管理

如何创建项目请参考2.2.创建项目. 通常web服务会要求注册的用户通过用户名和密码登录,然后才可能管理自己的信息或者对一些页面进行授权,判断用户是否拥有执行某种操作的权限. Django已经提供了一个django.contrib.auth应用来处理登录,登出和权限验证,同时还提供了django.contrib.admin应用来管理用户.可以参考你的虚拟python环境的/lib/python27/site-packges/django/contrib/admin里面的文件和源码. 我们要做的就

django 基于proxy实现用户权限管理

项目中经常会遇到用户权限管理的问题,django adminsite已经提供非常实用的用户权限管理机制.不过有些时候,我们希望根据相关用户属性来过滤adminsite中显示的内容.下文将结束如何实现: 原始类 假设我有这么一个问卷类,基于这个类可以实现增删改查的功能 class wenjuan(models.Model): """ 问卷 """ name=models.CharField(u'问卷名称',max_length=128) breif

[Django]用户权限学习系列之设计自有权限管理系统设计思路

若在阅读本片文章遇到权限操作问题,请查看本系列的前两章! http://www.cnblogs.com/CQ-LQJ/p/5609690.html和http://www.cnblogs.com/CQ-LQJ/p/5604331.html 现在步入正题,这篇文章是关于自有权限管理系统设计的思路描述,自有权限管理系统是抛弃django自带的后台管理界面,基于自己编写的权限管理界面对用户权限的管理! 首先上图:(自己设计的权限系统界面,代码将后续文章中写出) 权限管理界面主要是添加和删除权限,查看官方

Django—内置用户权限管理

内置用户权限管理 对于注册.登录.验证等功能我们可以自己编写用户管理应用,但Django也有一个内置的用户权限管理系统.也是很强大的. 在哪可以看到? 关于用户的信息都存放在这个表中. auth模块 from django.contrib import auth 其中有几个常用的方法: authenticate() 提供了用户认证功能,即验证用户名以及密码是否正确,一般需要username .password两个关键字参数. 如果认证成功(用户名和密码正确有效),便会返回一个 User 实例对象

基于Django实现RBAC权限管理

概述 RBAC(Role-Based Access Control,基于角色的访问控制),通过角色绑定权限,然后给用户划分角色.在web应用中,可以将权限理解为url,一个权限对应一个url. 在实际应用中,url是依附在菜单下的,比如一个简单的生产企业管理系统,菜单可以大致分为以下几块:制造.资材.生产管理.人事.财务等等.每个菜单下又可以有子菜单,但最终都会指向一个url,点击这个url,通过Django路由系统执行一个视图函数,来完成某种操作.这里,制造部的员工登录系统后,肯定不能点击财务