基于Django的权限管理平台

目录

单元一:项目准备

任务一:创建项目

[1.1配置 DRF 模型](#1.1配置 DRF 模型)

任务二:设置CSRF令牌

2.1创建app包

2.2检查浏览器Cookies权限

2.3获取cookies

单元二:用户平台

任务一:用户数据模型搭建

1.1创建user模块

1.2生成并执行迁移文件

任务二:列表分页功能

2.1技术栈

2.2知识解析

2.3功能实现

任务三:添加功能

3.1技术栈

3.2功能实现

任务四:修改功能

4.1技术栈

4.2功能实现

任务五:更新修改功能

5.1功能实现

任务六:删除功能

6.1技术栈

6.2功能实现

任务七:重置密码功能

7.1技术栈

7.2功能实现

任务八:状态更新功能

任务九:用户分配角色功能

单元三:角色平台

任务一:分页查询功能

1.1技术栈

1.2功能实现

任务二:角色的更新修改功能

2.1功能实现

任务三:删除管理功能

任务四:权限菜单树

4.1技术栈

4.2功能实现

任务五:根据角色分配菜单功能

5.1技术栈

5.2功能实现

单元四:菜单平台

任务一:菜单分页功能

任务二:菜单的添加修改功能

任务三:树形菜单查询

3.1技术栈

3.2功能实现

单元五:登录平台

6.1技术栈

6.2功能实现


单元一:项目准备

任务一:创建项目

和上述一样

1.1配置 DRF 模型

接下来,使用 DRF 来创建序列化器、视图和 URL 路由,以提供对上述模型的 API 访问。

安装 DRF

可以通 过 pip 进行安装:

复制代码
pip install djangorestframework

然后,在 settings.py 文件中添加 rest_framework 到INSTALLED_APPS 列表中: INSTALLED_APPS = ... 'rest_framework',

任务二:设置CSRF令牌

2.1创建app包

Django框架 | 0基础入门学习博客,这里不在赘述。

2.2检查浏览器Cookies权限

允许Cookies使用

2.3获取cookies

通过写测试函数,在函数中强制生成令牌

使用get_token(request) 生成CSRF令牌,通过set_cookie将令牌设置到响应头

复制代码
# 测试

class Testview(View):

    def get(self,request):

        response = JsonResponse({"code":200,"msg":"测试"})

        response.set_cookie('csrftoken', get_token(request))

        return response

在Postman中进行测试,获取CSRF令牌,如果没有进行CSRF令牌设置,后续会出问题。

在Postman的Headers中填入SCRF令牌

注意,不能设置成普通的Token,X- 是必要的

单元二:用户平台

任务一:用户数据模型搭建

1.1创建user模块

设置user实体类,在实体类中定义数据库表的字段

verbose_name:可读文字,用于管理员后台显示

复制代码
from django.db import models

# user实体类
class user(models.Model):
    username=models.CharField(max_length=100,null=True,unique=True,verbose_name="用户姓名")
    password=models.CharField(max_length=100,null=True,verbose_name='密码')
    avater=models.CharField(max_length=255,null=True,verbose_name="用户头像")
    email=models.CharField(max_length=100,null=True,verbose_name="用户邮箱")
    phonenumber=models.CharField(max_length=12,null=True,verbose_name="用户手机号")

    login_date = models.DateField(null=True, verbose_name="最后登录时间")
    status = models.IntegerField(null=True, verbose_name="帐号状态(0 正常 1 停用)")
    create_time = models.DateField(null=True, verbose_name="创建时间", )
    update_time = models.DateField(null=True, verbose_name="更新时间")
    remark = models.CharField(max_length=500, null=True, verbose_name="备注")

    class Meta:
        db_table = "user"

1.2生成并执行迁移文件

生成迁移文件:

manager.py 命令工具:makemigrations user 生成迁移文件

执行迁移文件:

manager.py 命令工具:migrate user

刷新查看数据库表

任务二:列表分页功能

2.1技术栈

1.Django View:基于类的视图处理HTTP请求

  1. Django Paginator:分页工具,实现数据分页逻辑

  2. QuerySet API: 数据库查询集操作(如**.all()** , .order_by()

  3. JSON 数据处理: 解析请求体中的JSON数据

  4. JsonResponse: 返回JSON格式的响应

2.2知识解析

(1) 请求数据处理

data = json.loads(request.body.decode("utf-8"))

通过request.body 获取请求体

通过decode("utf-8")解码为字符串

json.loads()解析JSON数据为Python字典

(2) 分页器逻辑

paginator = Paginator(queryset, pageSize)

userlist = paginator.page(pageNum)

Paginator: Django内置分页类

queryset: 查询集(需先排序避免分页混乱),order_by()排序

per_page: 每页条数

page(): 获取指定页码的数据页对象

2.3功能实现

复制代码
class PageList(View):
    def post(self,request):
        # 1.解析请求体中的JSON数据
        data=json.loads(request.body.decode("utf-8"))
        # 2.获取分页参数
        pageSize=data.get("pageSize")   #每页数据量
        pageNum=data.get("pageNum")     #展示(第一页)第几页
        print(f"请求分页,每页{pageSize}条,现在是第{pageNum}页")

        # 构建查询并排序查询集
        queryset = user.objects.all().order_by('id')  # 排序
        # 创建分页器对象
        paginator=Paginator(user.objects.all(),pageSize)
        # 获取指定页码的数据页
        userlist=paginator.page(pageNum)
        User=list(userlist.object_list.values())
        total=paginator.count
        return JsonResponse({
            "code":200,
            "msg":"分页成功",
            "data":User,
            "total":total
        })

示例:

任务三:添加功能

3.1技术栈

1.ORM 模型(对象关系映射) :通过 newlist.save() 将数据存入数据库,说明使用了 Django 的模型层。

2 .RESTful API 设计:返回 JSON 格式的响应({"code": 200, "msg": 添加成功"}),方便进行前后端交互。

3 .模型字段:从数据库中获取值,在赋值给模型,例如:username=data.get("username")

3.2功能实现

复制代码
# 增
class AddView(View):
    def post(self,request):
        data=json.loads(request.body.decode("utf-8"))
        newlist=user(username=data.get("username"),
                     password=data.get("password"),
                     email=data.get("email"),
                     phonenumber=data.get("phonenumber")
                     )
        newlist.status=data.get("status")
        newlist.create_time=datetime.datetime.now()
        newlist.save()
        return JsonResponse({
            "code":200,
            "msg":"添加成功"
        })

示图:

任务四:修改功能

4.1技术栈

  1. ORM(对象关系映射):通过id,查询相关的所有记录

  2. Python 标准库:利用了json模块和datatime模块

3.HTTP协议:处理Post请求

4.数据库操作:查询数据在进行修改

5.前后端交互,使用restful API返回json响应

4.2功能实现

复制代码
# 改
class UpdataView(View):
    def post(self,request):
        data=json.loads(request.body.decode('utf-8'))
        newlist=user.objects.get(id=data.get("id"))
        newlist.username=data.get("name")
        newlist.password=data.get("password")
        newlist.phonenumber=data.get("phonenumber")
        newlist.email=data.get("email")
        newlist.update_time=datetime.datetime.now()
        newlist.save()
        return JsonResponse({
            "code":200,
            "msg":"修改成功"
        })

示图:

任务五:更新修改功能

通过 user_id == data'id'进行判断用户是否存在。如果存在进行修改功能,如果不存在进行修改功能。

5.1功能实现

复制代码
class AddorUpdata(View):
    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        user_id = data.get("id")  # 使用 get() 避免 KeyError

        # 新增逻辑:id 不存在或为空
        if not user_id:
            newlist = user(
                username=data.get("username"),
                password=data.get("password"),
                email=data.get("email"),
                phonenumber=data.get("phonenumber")
            )
            newlist.status = data.get("status")
            newlist.create_time = datetime.datetime.now()
            newlist.save()
            return JsonResponse({"code": 200, "msg": "添加成功"})

        # 修改逻辑:id 存在
        else:
            try:
                newlist = user.objects.get(id=user_id)
                newlist.username = data.get("username")
                newlist.password = data.get("password")
                newlist.phonenumber = data.get("phonenumber")
                newlist.email = data.get("email")
                newlist.update_time = datetime.datetime.now()
                newlist.save()
                return JsonResponse({"code": 200, "msg": "修改成功"})
            except user.DoesNotExist:
                return JsonResponse({"code": 404, "msg": "用户不存在"}, status=404)

示图:

任务六:删除功能

6.1技术栈

1.ORM 批量删除:通过 id 列表批量删除记录,user.objects.filter(id__in=data).delete()

  1. 事务管理:with transaction.atomic(): 确保删除操作的原子性(要么全部成功,要么全部回滚)

6.2功能实现

复制代码
# 删除
class deleteView(View):
    def delete(self,request):
        data=json.loads(request.body.decode("utf-8"))
        with transaction.atomic():
            delresult=user.objects.filter(id__in=data).delete()
            print(delresult)
        return JsonResponse({
                'code':200,
                'msg':'删除成功'
            })

示图:

任务七:重置密码功能

7.1技术栈

1.请求参数处理:request.GET.get('id'):从 URL 查询参数中获取 id,(如 /resetpassword/?id=12)

2.其余和上述一样

7.2功能实现

复制代码
# 重置密码
class PasswordView(View):
    def get(self,request):
        newid=request.GET.get('id')
        print(newid)
        if not newid :
            return JsonResponse({
                "code":400,
                "msg":"没有找到相关id"
            })
        newlist=user.objects.get(id=newid)
        newlist.password=111111
        newlist.update_time=datetime.datetime.now()
        newlist.save()
        return JsonResponse({
            "code":200,
            "msg":"密码重置成功"
        })

示图:

任务八:状态更新功能

复制代码
# 更新状态
class StatusView(View):
    def get(self,request):
        newid=request.GET.get('id')
        print(newid)
        if not newid  :
            return JsonResponse({
                "code":400,
                "msg":"没有找到相关id"
            })
        newlist=user.objects.get(id=newid)
        newlist.status=1
        newlist.password=111111
        newlist.update_time=datetime.datetime.now()
        newlist.save()
        return JsonResponse({
            "code":200,
            "msg":"状态重置成功"
        })

示图:

任务九:用户分配角色功能

采用先删除后全量插入的模式

复制代码
# 用户分配角色功能
class GrantView(View):
    def post(self,request):
        # 1. 解析请求数据
        data=json.loads(request.body.decode("utf-8"))
        # 2. 获取用户ID和角色ID列表
        user_id=data.get("user_id",1)
        roleidList=data.get("role_id",[])
        print(user_id,roleidList)
        # 3. 删除该用户原有的所有角色关联
        UserRole.objects.filter(user_id=user_id).delete()
        # 4. 为该用户添加新的角色
        for roleid in roleidList:
            userrole=UserRole(user_id=user_id,role_id=roleid)
            userrole.save()
        return JsonResponse({
            "code":200,
            "msg":"权限功能分配成功"
        })

示图:

单元三:角色平台

任务一:分页查询功能

1.1技术栈

1.Django View:基于类的视图处理HTTP请求

  1. Django Paginator:分页工具,实现数据分页逻辑

  2. QuerySet API: 数据库查询集操作(如**.all()** , .order_by()

  3. JSON 数据处理: 解析请求体中的JSON数据

  4. JsonResponse: 返回JSON格式的响应

1.2功能实现

复制代码
class PageList_role(View):
    def post(self,request):
        # 1.解析请求体中的JSON数据
        data=json.loads(request.body.decode("utf-8"))
        # 2.获取分页参数
        pageSize=data.get("pageSize")   #每页数据量
        pageNum=data.get("pageNum")     #展示(第一页)第几页
        print(f"请求分页,每页{pageSize}条,现在是第{pageNum}页")

        # 构建查询并排序查询集
        queryset = Role.objects.all().order_by('id')  # 排序
        # 创建分页器对象
        paginator=Paginator(Role.objects.all(),pageSize)
        # 获取指定页码的数据页
        rolelist=paginator.page(pageNum)
        role=list(rolelist.object_list.values())
        total=paginator.count
        return JsonResponse({
            "code":200,
            "msg":"分页成功",
            "data":role,
            "total":total
        })

示图:

任务二:角色的更新修改功能

技术与user的一样

2.1功能实现

复制代码
class AddUpdata_role(View):
    def post(self,request):
        data = json.loads(request.body.decode("utf-8"))
        role_id = data.get('id')
        if not role_id :
            newlist = Role(name=data.get("name"),
                           code=data.get("code"),
                           remark=data.get("remark")
                           )
            # newlist.status = data.get("status")
            newlist.create_time = datetime.datetime.now()
            newlist.update_time=datetime.datetime.now()
            newlist.save()
            return JsonResponse({
                "code": 200,
                "msg": "添加成功"
            })
        else:
            try:
                newlist = Role.objects.get(id=role_id)
                newlist.name = data.get("name",Role.name)
                newlist.code = data.get("code",Role.code)
                newlist.remark = data.get("remark",Role.remark)
                newlist.update_time = datetime.datetime.now()
                newlist.save()
                return JsonResponse({
                    "code": 200,
                    "msg": "修改成功"
                })
            except Role.DoesNotExist:
                return JsonResponse({
                    "code":404,
                    "msg":"角色不存在"
                })

任务三:删除管理功能

超级管理员可以管理用户和管理员,管理员只可以管理用户,用户没有管理权限

复制代码
class deleteView_role(View):
    def delete(self,request):
        data=json.loads(request.body.decode("utf-8"))
        with transaction.atomic():
            delresult=Role.objects.filter(id__in=data).delete()
            print(delresult)
        return JsonResponse({
                'code':200,
                'msg':'删除成功'
            })

任务四:权限菜单树

4.1技术栈

1.使用了Django REST Framework的序列化器(SysMenuSerializer)

2.buildTree方法:实现从扁平菜单列表到树形结构的转换,使用字典存储中间结果,使用两阶段处理:序列化+构建层级关系

4.2功能实现

复制代码
# 权限菜单树(查询)
class MenuTreeList_role(View):
    # 构建权限菜单树的方法
    #  参数: menu_items:从数据库查询出来的所有菜单列表(包含多个 Menu )
    #  返回: 整理好的树形菜单结构
    def buildTree(self, menu_items):
        resultList = []    #用于存储最终的树形结构
        menu_dict = {}    # 创建空字典

        # 第一步:将所有菜单项存入字典,并初步序列化
        # 1.对每个菜单进行遍历
        for menu in menu_items:
            # 2.使用 SysMenuSerializer 将每个菜单对象序列化为字典
            serialized_menu = SysMenuSerializer(menu).data
            # 3.每个菜单都添加children空列表
            serialized_menu['children'] = []
            # 把每个菜单存入空字典,key:value,菜单ID:菜单对象
            menu_dict[menu.id] = serialized_menu

        # 第二步:遍历菜单字典的每一行(所有菜单项)
        for menu_id, menu_obj in menu_dict.items():
            # 在序列化好的menu中获取meun id
            current_menu = Menu.objects.get(id=menu_id)
            # 获取parent_id的值
            parent_id = current_menu.parent_id
            # 判断parent_id是否为0
            if parent_id == 0:
                # 如果为0,就把它添加到存储最终的树形结构的空列表中 resultList=[] 顶级
                resultList.append(menu_obj)
            else:
                # 如果不为0,把它的id赋值到parent
                parent = menu_dict.get(parent_id)
                if parent:
                    parent['children'].append(menu_obj)
        return resultList
    # 排序
    def get(self,request):
        try:
            menuList=Menu.objects.order_by("order_num")
            # 构建菜单树
            tree_data=self.buildTree(menuList)
            return JsonResponse({
                "code": 200,
                "data":tree_data
                # "data": serialized_data
            })
        except Exception as e:
            return JsonResponse({
                "code": 500,
                "msg": str(e)
            }, status=500)

# 根据角色查询菜单功能
class MenuTree_role(View):
    def get(self,request):
        role_id=request.GET.get("role_id")
        rolemenu=SysRoleMenu.objects.filter(role_id=role_id).values("menu_id")
        menulistID=None
        for role in rolemenu:
            menulistID=role['menu_id']
        print(menulistID)
        return JsonResponse({
            "code":200,
            "menuIdlist":menulistID
        })

任务五:根据角色分配菜单功能

5.1技术栈

采用"全量替换"模式(删除所有与相关id有关的数据),先删除后插入,保证权限数据的最终一致性

5.2功能实现

复制代码
# 根据角色分配菜单功能
class GrantView_role(View):
    def post(self,request):
        # 1. 解析请求数据
        data=json.loads(request.body.decode("utf-8"))
        # 2. 获取菜单ID和角色ID列表
        role_id=data.get("role_id",1)
        menuidList=data.get("menu_id",[])
        print(role_id,menuidList)
        # 3. 删除该角色原有的所有菜单关联
        SysRoleMenu.objects.filter(role_id=role_id).delete()
        # 4. 为该角色添加新的菜单
        for menuid in menuidList:
            userrole=SysRoleMenu(role_id=role_id,menu_id=menuid)
            userrole.save()
        return JsonResponse({
            "code":200,
            "msg":"权限功能分配成功"
        })

单元四:菜单平台

任务一:菜单分页功能

复制代码
# 分页
class PageList_menu(View):
    def post(self,request):
        # 1.解析请求体中的JSON数据
        data=json.loads(request.body.decode("utf-8"))
        # 2.获取分页参数
        pageSize=data.get("pageSize")   #每页数据量
        pageNum=data.get("pageNum")     #展示(第一页)第几页
        print(f"请求分页,每页{pageSize}条,现在是第{pageNum}页")

        # 构建查询并排序查询集
        queryset = Menu.objects.all().order_by('id')  # 排序
        # 创建分页器对象
        paginator=Paginator(Menu.objects.all(),pageSize)
        # 获取指定页码的数据页
        menulist=paginator.page(pageNum)
        menu=list(menulist.object_list.values())
        total=paginator.count
        return JsonResponse({
            "code":200,
            "msg":"分页成功",
            "data":menu,
            "total":total
        })

任务二:菜单的添加修改功能

复制代码
# 菜单修改添加
class AddorUpdata_menu(View):
    def post(self,request):
        data = json.loads(request.body.decode("utf-8"))
        menu_id = data['id']
        if menu_id == data['id']:
            newlist = Menu(name=data.get("name"),
                           icon=data.get("icon"),
                           parent_id=data.get("parent_id"),
                           order_num=data.get("order_num"),
                           path=data.get("path"),
                           menu_type=data.get("menu_type"),
                           perms=data.get("perms"),
                           remark=data.get("remark"),
                           component=data.get("component")
                           )
            newlist.status = data.get("status")
            newlist.create_time = datetime.datetime.now()
            newlist.save()
            return JsonResponse({
                "code": 200,
                "msg": "添加成功"
            })
        else:
            newlist = Menu.objects.get(id=data.get("id"))
            newlist.name = data.get("name")
            newlist.icon = data.get("icon")
            newlist.parent_id = data.get("parent_id")
            newlist.order_num = data.get("order_num")
            newlist.path = data.get("path")
            newlist.menu_type = data.get("menu_type")
            newlist.perms = data.get("perms")
            newlist.remark = data.get("remark")
            newlist.component = data.get("component")
            newlist.update_time = datetime.datetime.now()
            newlist.save()
            return JsonResponse({
                "code": 200,
                "msg": "修改成功"
            })

任务三:树形菜单查询

3.1技术栈

  1. 数据序列化:使用values()直接转换为字典
  2. 数据库操作:全表查询(Menu.objects.all()),直接值转换(.values())

3.2功能实现

复制代码
# 树形菜单查询
class ListAll_menu(View):
    def get(self,request):
        menulist=list(Menu.objects.all().values())
        print(menulist)
        return JsonResponse({
            "code":200,
            "msg":"查询成功",
            "data":menulist
        })

单元五:登录平台

6.1技术栈

1.使用Django REST Framework的JWT组件(通过api_settings调用)

2.认证:基础认证通过用户名和密码进行认证,令牌认证通过JWT的生成与返回进行认证

6.2功能实现

复制代码
# 登录
class loginView_user(View):
    def post(self, request):
        data = json.loads(request.body)
        username = data.get("username")
        password = data.get("password")
        # 使用 Django 的认证系统验证用户
        User=user.objects.get(username=username,password=password)

        if user is not None:
            # 生成 JWT token
            api_payload = api_settings.JWT_PAYLOAD_HANDLER
            api_encode = api_settings.JWT_ENCODE_HANDLER
            payload = api_payload(User)
            token = api_encode(payload)

            return JsonResponse({
                "code": 200,
                "token": token,
                "msg": "登录成功"
            })
        else:
            return JsonResponse({
                "code": 400,
                "msg": "用户名或密码错误"
            })

示图:

相关推荐
DLYSB_30 分钟前
存储运维实战:基于 Ceph Event 监听与 Python 适配器的分布式存储健康度物理声光响应架构
运维·ceph·python·报警灯
陈随易35 分钟前
FFmpeg 9.0 发布,代号 Lei,音视频处理再升级
前端·后端·程序员
阿童木写作1 小时前
跨境图片翻译工具多合一,批量图片视频字幕翻译加智能抠图
人工智能·python·音视频·语音识别
阿童木写作2 小时前
Python实现Temu图片批量翻译自动化教程
运维·人工智能·python·自动化
就是一只白4 小时前
复制地理信息python版本
python
凌虚4 小时前
面向 MySQL 用户的 PostgreSQL 快速上手指南
数据库·后端·架构
看浪的路人4 小时前
第1讲:Agent 到底是什么?和 Chatbot 有什么区别
python·ai
瓦学妹5 小时前
什么是网络索引?它是如何工作的?
大数据·网络·python·网络爬虫
IT_陈寒5 小时前
Vite静态资源引用这个坑我踩得有点疼
前端·人工智能·后端
天天爱吃肉82185 小时前
商用车多体动力学实战笔记|第6篇:动力传动系统(发动机、变速箱、分动器、TCS、LSD限滑差速)
大数据·人工智能·笔记·python·嵌入式硬件·汽车