首页 > 编程语言 >python django中的权限控制

python django中的权限控制

时间:2023-08-03 09:33:14浏览次数:36  
标签:name level python request django url dict user 权限

权限控制

基于form组件实现

1. 配置文件编写权限关系表

有权限控制,意味着要登录,需要提前把登录页面放到白名单,在setting.py文件写入白名单内的路径不做访问控制和登录认证
WHITE_URL = ["/web/login/", "/web/sms_login", "web/sms_send", "/web/logout/"]
在setting.py文件写入权限关系表,实现ADMIN,BOSS,CUSTOMER三者不同的访问路径

MY_PERMISSION = {
    "ADMIN": {
        "home": {"text": "主页", "parent": None},
        "order": {"text": "订单", "parent": None},
        "level_list": {"text": "级别展示", "parent": None},
        "level_add": {"text": "级别新增", "parent": "level_list"},
        "customer_list": {"text": "用户管理", "parent": None},
    },
    "BOSS": {
        "home": {"text": "主页", "parent": None},

        "order": {"text": "订单", "parent": None},
        "order_add": {"text": "订单新增", "parent": "order"},

        "level_list": {"text": "级别展示", "parent": None},
        "level_add": {"text": "级别新增", "parent": "level_list"},
        "level_edit": {"text": "级别编辑", "parent": "level_list"},
        "level_del": {"text": "级别删除", "parent": "level_list"},

        "customer_list": {"text": "用户管理", "parent": None},
        "customer_add": {"text": "新增用户", "parent": "customer_list"},
        "customer_edit": {"text": "用户编辑", "parent": "customer_list"},
        "customer_del": {"text": "用户删除", "parent": "customer_list"},
    },
    "CUSTOMER": {
        "home": {"text": "主页", "parent": None},
        # "order": None,
    }
}

2. 通过django的session组件,对用户登录后将角色传入到session中

user_obj = models.Customer.objects.filter(username=user, password=pwd).first()
if not user_obj:
    userform.add_error("acc_password", "账号或者用户名错误")
    return render(request, "login.html", {"userform": userform})
mapping = {"root": "BOSS", "admin": "ADMIN"}
request.session[settings.SESSION_KEY] = {"name": user, "role": user_obj.get_role_level_display()}
return redirect(settings.HOME_PAGE)

get_role_level_display() 是为了展示下面role_level里的choice字段
model代码
class Customer(ActiveBaseModel):
    role_Choices=((30,"BOSS"),(20,"ADMIN"),(1,"CUSTOMER"))
    username = models.CharField(max_length=20, verbose_name="用户名称")
    password = models.CharField(max_length=20, verbose_name="密码")
    ...省略...
    level =models.ForeignKey(verbose_name="会员等级",to="Level",on_delete=models.CASCADE,default=1)
    role_level = models.SmallIntegerField(choices=role_Choices,default=1,verbose_name="角色级别")
    # limit_choices_to 可以用来对关联内容做限制展示
    # level = models.ForeignKey(verbose_name="级别", to="Level", on_delete=models.CASCADE, limit_choices_to={'active': 1})
    create_date=models.DateTimeField(verbose_name="创建日期",auto_now_add=True)

3. 通过中间件读取里面的角色和配置文件角色相关的权限

搞懂中间件的先后执行顺序

process_request 是第一步,通过这步获取session内的数据,同时做初步的登录访问控制路由
process_view 是在上一步获取权限的基础上进行鉴权操作.

# 用来通过实例对象,将权限,角色等信息规范的写入到对应的属性中去
class UserDict():
    def __init__(self,name,role):
        self.name=name
        self.role=role
        self.detail = settings.MY_MENU.get(role)
        self.permission=settings.MY_PERMISSION.get(role)
        self.path = None

# 将UserDict通过中间件赋值到request对象中,后续可以通过request.user_dict.permission获取登录角色的权限
class AuthMiddleware(MiddlewareMixin):
    def process_request(self, request):
        # 白名单url不需要登录就能访问
        if request.path_info in settings.WHITE_URL:
            return None

        # 检测是否已经登录,判断session中的userino的session信息
        user_dict = request.session.get(settings.SESSION_KEY)
        print("user_dict>>", user_dict)
        if not user_dict:
            return redirect(settings.LOGIN_HOME)

        # 也可以 request.user_dict.name = user_dict.get("name"),但是推荐下面这样写
        # 因为类属性字段都会统一,而且调用时候也方便直接获取对象的属性即可
        # 并且在html模版中也可以传入request对象,如果要获取用户名字就是request.user_dict.name
        request.user_dict=UserDict(**user_dict)

    def process_view(self,request,callback,callback_args,callback_kwargs):
        # 无须登录就能访问的白名单没有给request添加user_dict类,放行
        if not hasattr(request,"user_dict"):
            return None


        url_name = request.resolver_match.url_name
        if not request.user_dict.permission.get(url_name):
            return HttpResponse("没有权限进入")

        # 添加访问路径
        visit_path_list=[]
        visit_path_list.append(request.user_dict.permission[url_name]["text"])

        while request.user_dict.permission[url_name]["parent"]:
            print("url_name>>", url_name)
            father_menu = request.user_dict.permission[url_name]["parent"]
            father_menu_text = request.user_dict.permission[father_menu]["text"]

            visit_path_list.append(father_menu_text)
            url_name=father_menu
        visit_path_list.reverse()
        print("访问路径是",visit_path_list) #访问路径是 ['订单', '订单新增']
        request.user_dict.path=visit_path_list

4. 自定义模版

理论上 第3步已经实现了权限控制,这一步是增加体验感,对于没权限的功能,在前端页面上不做展示.
这里自定义了添加,编辑,删除的自定义simple_tag
还自定义了过滤器,这里是根据功能选择不同的自定义模版类型,
选择自定义simple_tag是因为要传入多个参数,而自定义的过滤器只能传2个,但是simple_tag只能返回字符串,因此需要mark_safe进行转换成a标签
选择自定义过滤器 是因为要实现table标签 的列是否显示,如果登录角色没有edit和delete的权限,那么操作这列没必要显示出来,因此返回的值为布尔值即可

from django import template
from django.utils.safestring import mark_safe
from django.shortcuts import reverse
register=template.Library()

@register.simple_tag()
def add_permission(request,url_reverse_name,*args,**kwargs):
    # 传入url别名反向生成url
    actual_url = reverse(url_reverse_name,*args,**kwargs)
    # 如果权限中有url别名 表示有权限
    if not request.user_dict.permission.get(url_reverse_name):
       return ""
    else:
        html_tag = '<a class="btn btn-success" href="{}">新增</a>'.format(actual_url)
        # html_tag = '<a class="btn btn-success" >新增</a>'
        return mark_safe(html_tag)



@register.simple_tag()
def edit_permission(request,url_reverse_name,*args,**kwargs):
    # 这里的edit和上面的add url是不同的,edit和delete是要传入pk值的,反向解析通过kwargs获取
    actual_url = reverse(url_reverse_name, args=args,kwargs=kwargs)
    # 如果权限中有url别名 表示有权限
    if not request.user_dict.permission.get(url_reverse_name):
       return ""
    else:
        # html_tag = '<td><a class="btn btn-primary" href="{}">编辑</a> </td>'.format(actual_url)
        html_tag = '<a class="btn btn-primary" href="{}">编辑</a> '.format(actual_url)
        return mark_safe(html_tag)




@register.simple_tag()
def del_permission(request,url_reverse_name,*args,**kwargs):
    # 这里的edit和上面的add url是不同的,edit和delete是要传入pk值的,反向解析通过kwargs获取
    actual_url = reverse(url_reverse_name, args=args,kwargs=kwargs)
    if not request.user_dict.permission.get(url_reverse_name):
       return ""
    else:
        # html_tag = '<td><a class="btn btn-danger" href="{}">删除</a> </td>'.format(actual_url)
        html_tag = '<a class="btn btn-danger" href="{}">删除</a>'.format(actual_url)
        return mark_safe(html_tag)



@register.filter()
def has_permission(request,tags):
    #filter只能传2个参数,这里我们把多个反向解析的url别名用逗号拼接传入tags
    tag_lists = tags.split(",")
    for tag_List in tag_lists:
        if tag_List in request.user_dict.permission.keys():
            return True

    return False

5. 在html模版渲染中写入判断条件,实现动态展示

{% extends "home.html" %}

{% load permission_tags %}
{% block level %}
    <div>
        {#        <a class="btn btn-success" href={% url 'level_add' %}>新增</a>#}
        {% add_permission request "level_add" %}
    </div>
    <table class="table table-striped table-condensed table-hover">
        <thead>
        <tr>
            <th>ID</th>
            <th>标题</th>
            <th>折扣</th>
            {% if request|has_permission:"level_edit,level_del" %}    如果无删除和编辑权限,不显示操作这列
                <th>操作</th>
            {% endif %}
        </tr>
        </thead>
        <tbody></tbody>
        {% for obj in queryset %}
            <tr>
                <td>{{ obj.id }}</td>
                <td>{{ obj.title }}</td>
                <td>{{ obj.discount }} <span>%</span></td
                {% if request|has_permission:"level_edit,level_del" %}     如果无删除和编辑权限,不显示操作这列
                <td>
                    {% edit_permission request "level_edit" pk=obj.id %} {# 编辑按钮 #}   如果无编辑权限,不显示编辑按钮
                    {% del_permission request "level_del" pk=obj.id %} {# 删除按钮 #}    如果无删除权限,不显示删除按钮
                </td>
                {% endif %}


            </tr>
        {% endfor %}
    </table>

{% endblock %}

标签:name,level,python,request,django,url,dict,user,权限
From: https://www.cnblogs.com/Young-shi/p/17601329.html

相关文章

  • delete_by_query删除数据(python)
     fromelasticsearchimportElasticsearchimportos,json,urllib,datetime,shutil,random,uuidimporttimeimportrandomfromelasticsearchimporthelpersfromrandomimportchoiceif__name__=='__main__':print("开始时间:"+time.s......
  • Python顺序查找:简单而强大的数据搜索方法
    顺序查找(SequentialSearch)是一种简单直观的搜索算法,用于在无序数组中查找特定元素。它的基本思想是逐个遍历数组中的元素,直到找到目标元素或遍历完整个数组。本文将介绍顺序查找的基本原理,并通过Python代码进行详细讲解。一、原理顺序查找的原理非常简单,基本步骤如下:从数组的......
  • 算法-10--python shuffle函数_python中shuffle()方法的功能详解
     pythonshuffle函数_python中shuffle()方法的功能详解: python的概率分布中,洗牌算法是通过shuffle()方法实现的,shuffle()方法将列表的所有元素打乱,随机排列。Python既可以使用random.shuffle对列表进行洗牌,也可以使用random.shuffle随机播放字符串列表,本文向大家介绍python中......
  • 常见距离计算的Python实现
    常见的距离有曼哈顿距离、欧式距离、切比雪夫距离、闵可夫斯基距离、汉明距离、余弦距离等,用Python实现计算的方式有多种,可以直接构造公式计算,也可以利用内置线性代数函数计算,还可以利用scipy库计算。1.曼哈顿距离也叫城市街区距离,是两点差向量的L1范数,也就是各元素的绝对值之和......
  • 《流畅的Python第二版》读书笔记——文本和字节序列
    引言这是《流畅的Python第二版》抢先版的读书笔记。Python版本暂时用的是python3.8。为了使开发更简单、快捷,本文使用了JupyterLab。Python3明确区分了人类可读的字符串和原始的字节序列。新内容简介新增了对emoji表示字符的描述。字符问题字符串是个简单的概念:一个字符串是一个字......
  • 使用python进行贝叶斯统计分析|附代码数据
    原文链接:http://tecdat.cn/?p=7637最近我们被客户要求撰写关于贝叶斯统计的研究报告,包括一些图形和统计输出。本文讲解了使用PyMC3进行基本的贝叶斯统计分析过程. ( 点击文末“阅读原文”获取完整代码数据******** )。  #Importsimportpymc3aspm#python的概率......
  • 贝叶斯网络python实战(以泰坦尼克号数据集为例,pgmpy库)
    贝叶斯网络python实战(以泰坦尼克号数据集为例,pgmpy库)leida_wt 2019-03-2423:05:36  16815  收藏 140分类专栏: 机器学习 文章标签: pgmpy 贝叶斯网络 泰坦尼克 机器学习 图网络版权 文章目录贝叶斯网络简介贝叶斯推断思路贝叶斯网络贝叶斯网络的实现应用步骤泰坦尼克......
  • Python教程(6)——Python变量的基础类型。|整数类型|浮点数类型|字符串类型|布尔类型|
    学习编程语言,不得不忽视变量这个概念。Python中的变量是用于存储数据的名称,你可以将值赋给变量,并在程序的其他地方使用该变量来引用该值。变量在程序中起到存储和操作数据的作用。如果学过C/C++语言的同学,定义了变量后,需要加个类型的限制,比如intage=28doublemoney=10.2......
  • 模型:Django与Mysql交互
     1、创建数据库用户前提是已经在本机或者服务器上安装了mysql。createdatabaseslw;createuser'slw'@'%'identifiedby'pwd'grantallprivilegesonslw.*to'slw'@'%'identifiedby'pwd'withgrantoption;flushprivile......
  • MySQL提权之启动项提权——开机启动的程序,那时候启动的程序权限都是system
    关于MySQL的启动项提权,听其名知其意。就是将一段VBS脚本导入到 C:\DocumentsandSettings\AllUsers\「开始」菜单\程序\启动下,如果管理员重启了服务器,那么就会自动调用该脚本,并执行其中的用户添加及提权命令!这里有两种思路:1.如果 C:\DocumentsandSettings\AllUsers\「......