首页 > 其他 > 详细

如何制作一个简单的django权限组件

时间:2018-10-10 22:51:07      阅读:324      评论:0      收藏:0      [点我收藏+]

第一步:

  新建一个app

第二步:目录结构

           技术分享图片

  第三步:代码如下

第一步:写models

技术分享图片
from django.db import models


# 定义一级菜单
class Menu(models.Model):
    title = models.CharField(max_length=32, unique=True)  # 名称
    icon = models.CharField(max_length=32, null=True, blank=True)  # 图标代码:可以为空   

    def __str__(self):
        return self.title


# 定义权限
class Permission(models.Model):
    """
    权限表
    """
    title = models.CharField(verbose_name=‘标题‘, max_length=32)  # 定义标题,动态生成时候,要用到
    url = models.CharField(verbose_name=‘含正则的URL‘, max_length=128)  # url地址
    name = models.CharField(max_length=32, verbose_name=‘url别名‘, unique=True)  # 每个url的别名,唯一,且不能为空
    menu = models.ForeignKey(‘Menu‘, null=True, blank=True, verbose_name=‘一级菜单‘)  # 关联的一级菜单
    prent = models.ForeignKey(‘Permission‘, null=True, blank=True, verbose_name=‘关联列表‘)  # 自己关联自己中的某个列表要使用的

    def __str__(self):
        return self.title


class Role(models.Model):
    """
    角色
    """
    title = models.CharField(verbose_name=‘角色名称‘, max_length=32)  # 定义角色的名字
    permissions = models.ManyToManyField(verbose_name=‘拥有的所有权限‘, to=‘Permission‘, blank=True)

    # 和权限多对多关系
    def __str__(self):
        return self.title


# 定义用户
class UserInfo(models.Model):
    """
    用户表
    """
    name = 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)  # 多对多关联角色表

    def __str__(self):
        return self.name
models.py文件中内容

第二步:写server文件下的init_permission.py

技术分享图片
from django.conf import settings



# 获取当前登录用户的所有权限
def init_permission(request, user):
    rbac_list = user.roles.filter(permissions__url__isnull=False).values(
        ‘permissions__id‘, # 获取权限的id
        ‘permissions__url‘,# 获取权限的url
        ‘permissions__title‘,# 获取权限的名字
        ‘permissions__name‘,# 获取权限的别名
        ‘permissions__prent_id‘,# 获取关联列表的id
        ‘permissions__prent__name‘,# 获取关联列表的别名
        ‘permissions__menu_id‘,# 获取一级菜单的id
        ‘permissions__menu__title‘,# 获取一级菜单的名字
        ‘permissions__menu__icon‘,  # 获取一级菜单的图标代码
    ).distinct() # 去重

    url_dict = {}  # 该用户所有的权限
    menu_dic = {}  # 根据权限生成的菜单
    for i in rbac_list: # 循环所有筛选出来的内容
        """
        用每个权限的别名做key,
        value是[
            ‘url‘:权限的url,
            ‘id‘:每个权限的id,
            ‘pid‘:‘它所关联权限的id‘,
            ‘title‘:‘它自己的标题‘,
            ‘pname‘:‘它所关联权限的别名‘
            ]

        """
        url_dict[i[‘permissions__name‘]] = {‘url‘: i[‘permissions__url‘], 
                                            ‘id‘:i[‘permissions__id‘],
                                            ‘pid‘:i[‘permissions__prent_id‘],
                                            ‘title‘:i[‘permissions__title‘],
                                            ‘pname‘:i[‘permissions__prent__name‘],
                                            }
        # 获取一级菜单的id
        menu_id = i.get(‘permissions__menu_id‘)
        # 判断如果没有一级菜单的id就重新循环
        if not menu_id:
            continue
        # 判断一级菜单的id是否存在menu_dic这个字典里
        # 如果存在
        if menu_id not in menu_dic:
            """
            结构:
            一级菜单id = {
            ‘title‘:一级菜单的名称
            ‘icon‘:一级菜单的图标代码
            ‘children‘:[{
                
                ‘title‘:二级菜单的标题,
                ‘url‘:二级菜单的url
                ‘id‘:二级菜单的id
    
                }]}
                
            """
            menu_dic[i[‘permissions__menu_id‘]] = {
                ‘title‘: i[‘permissions__menu__title‘],
                ‘icon‘: i[‘permissions__menu__icon‘],
                ‘children‘: [
                    {‘title‘: i[‘permissions__title‘],
                     ‘url‘: i[‘permissions__url‘],
                     ‘id‘:i[‘permissions__id‘]
                     }
                ]
            }
        else:
            menu_dic[i[‘permissions__menu_id‘]][‘children‘].append({‘title‘: i[‘permissions__title‘],
                                                                    ‘url‘: i[‘permissions__url‘],
                                                                    ‘id‘: i[‘permissions_id‘]
                                                                    })
    
    # 把筛选出来的该用户所有权限和菜单结构全部存入到session中
    # settings.PERMISSION_SESSION_KEY和settings.MENU_SESSION_KEY:自己在自己的settings文件中设置
    request.session[settings.PERMISSION_SESSION_KEY] = url_dict
    request.session[settings.MENU_SESSION_KEY] = menu_dic
权限相关的所有代码

第三步:写middlewear下的rbac.py

技术分享图片
import re
from django.conf import settings
from django.shortcuts import HttpResponse
from django.utils.deprecation import MiddlewareMixin




# 中间件
class RbacPermissionMiddleware(MiddlewareMixin):
    
    def process_request(self, request):
        # 获取当前访问的地址
        current_url = request.path_info
        # 循环判断白名单,自己在settings设置自己的白名单
        for i in settings.WITER_LIST:
            if re.match(‘^%s$‘%i, current_url):
                return
        # 获取当前用户权限
        permissions_dict = request.session[settings.PERMISSION_SESSION_KEY]
        # 小菜单要使用
        request.breadcrumb_list=[{‘title‘:‘首页‘,‘url‘:‘/‘}]
        # 循环判断
        flag = False
        # 循环用户的所有权限
        for item in permissions_dict.values():
            # 正则匹配
            if re.match(item[‘url‘], current_url):
                # 匹配成功修改flag
                flag = True
                # 获取id,父级id,父级url别名
                id = item[‘id‘]
                pid = item[‘pid‘]
                pname = item[‘pname‘]
                # 判断是否有父级id
                if pid:
                    # 获取父级id,在动态生成菜单时要用
                    request.current_menu_id = pid
                    # 父级的url,title,和自己的url好和title
                    request.breadcrumb_list.extend([
                        {‘url‘:permissions_dict[pname][‘url‘],‘title‘:permissions_dict[pname][‘title‘]},
                        {‘url‘:item[‘url‘],‘title‘:item[‘title‘]},
                                                    ])
                else:
                    # 获取自己id,在动态生成菜单时要用
                    request.current_menu_id = id
                    # 自己的url好和title
                    request.breadcrumb_list.extend([
                        {‘url‘: item[‘url‘], ‘title‘: item[‘title‘]}
                    ])
                break
        # 判断当前用户是否有权限访问这个页面
        if not flag:
            return HttpResponse(‘你没有此权限‘)
中间件的代码

第四步:写templatetags下的rbac.py

技术分享图片
from django.conf import settings
from django import template
from collections import OrderedDict

register = template.Library()


# 设置左侧菜单的模板组件
@register.inclusion_tag(‘rbac/module.html‘)
def show_results(request):
    # 获取存储菜单的字典
    menu_dic = request.session[settings.MENU_SESSION_KEY]
    # 让字典变的有序,python3.6在一些特殊的情况下会变得无序
    order_dict = OrderedDict()
    # 循环这个字典,字典先排序
    for item in sorted(menu_dic):
        # 把这个字典里所有内容传入到有序字典里
        order_dict[item] = menu_dic[item]
        # 给所有的一级菜单中都加入一个hide(隐藏)
        order_dict[item][‘class‘] = ‘hide‘
        # 循环这个字典的二级菜单
        for i in order_dict[item][‘children‘]:
            # 判断当前访问的url的id是否是当前循环二级菜单的id
            if request.current_menu_id == i[‘id‘]:
                # 如果是的话,给他添加‘active‘和去除一级菜单的‘hide‘
                i[‘class‘] = ‘active‘
                order_dict[item][‘class‘] = ‘‘
    # 把字典出入html文件里
    return {‘menu_dic‘: order_dict}


# 设置小菜单
@register.inclusion_tag(‘rbac/breadcrumb.html‘)
def breadcrumb(request):
    # 把小菜单需要的列表传入
    return {‘breadcrumb_list‘: request.breadcrumb_list}


# 设置过滤器
@register.filter
def has_permission(request, name):
    # 判断传入的url别名是否在菜单字典中
    if name in request.session.get(settings.PERMISSION_SESSION_KEY):
        return True
标签代码
技术分享图片
<div class="multi-menu">
    {% for item in menu_dic.values %}
         <div class="item">
             <div class="title">
                 <span class="icon-wrap"><i class="fa {{ item.icon }}"></i></span>{{ item.title }}
             </div>
             <div class="body {{ item.class }}">
                 {% for per in item.children %}
                    <a href="{{ per.url }}" class="{{ per.class }}" >{{ per.title }}</a>
                 {% endfor %}
             </div>
         </div>
    {% endfor %}
</div>
module.html的代码
技术分享图片
<ol class="breadcrumb no-radius no-margin" style="border-bottom: 1px solid #ddd;">
    {% for item in breadcrumb_list %}
        {% if forloop.last %}
            <li class="active">{{ item.title }}</li>
            {% else %}
                <li><a href="{{ item.url }}">{{ item.title }}</a></li>
        {% endif %}
    {% endfor %}
</ol>
breadcrumb.html的代码

第五步:admin.py中的代码

技术分享图片
from django.contrib import admin
from rbac import models


class PermissionAdmin(admin.ModelAdmin):
    list_display = [‘title‘, ‘url‘,‘menu‘,‘prent‘,‘name‘] # 页面要显示的内容
    list_editable = [‘url‘,‘menu‘,‘prent‘,‘name‘]   # 可以在页面更改的内容



admin.site.register(models.Role)
admin.site.register(models.Permission, PermissionAdmin)
admin.site.register(models.UserInfo)
admin.site.register(models.Menu)
admin.py中的代码

有一些注释可能写的比较迷,直接贴图吧

左菜单/大菜单

技术分享图片

小菜单

技术分享图片

简单的组件写完了,组件的css和js代码根据自己设计的页面来写

 

 

组件的使用

第一步:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

如何制作一个简单的django权限组件

原文:https://www.cnblogs.com/chunqiuyu/p/9769280.html

踩
(0)
赞
(0)
   
举报
评论 一句话评论(0)
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!