码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-10-10 23:56:00      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:als   9.png   文件中   elf   png   新建   def   app   cpe   

第一步:

  新建一个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权限组件

标签:als   9.png   文件中   elf   png   新建   def   app   cpe   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!