基于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": "用户名或密码错误"
            })

示图:

相关推荐
YOULANSHENGMENG5 分钟前
linux 下python 调用c++的动态库的方法
c++·python
小希爸爸11 分钟前
2、中医基础入门和养生
前端·后端
SsummerC22 分钟前
【leetcode100】零钱兑换Ⅱ
数据结构·python·算法·leetcode·动态规划
一眼青苔1 小时前
切割PDF使用python,库PyPDF2
服务器·python·pdf
电商数据girl1 小时前
产品经理对于电商接口的梳理||电商接口文档梳理与接入
大数据·数据库·python·自动化·产品经理
盖世英雄酱581361 小时前
分布式ID所有生成方案
java·后端
小希爸爸1 小时前
1、中医基础入门和养生
前端·后端
敖云岚1 小时前
【AI】SpringAI 第五弹:接入千帆大模型
java·大数据·人工智能·spring boot·后端
桦说编程1 小时前
CompletableFuture典型错误 -- 代码出自某大厂
java·后端·响应式编程
三道杠卷胡1 小时前
【AI News | 20250424】每日AI进展
人工智能·pytorch·python·语言模型·github