基于Django的权限管理平台
目录
单元一:项目准备
任务一:创建项目
1.1配置 DRF 模型
任务二:设置CSRF令牌
2.1创建app包
2.2检查浏览器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请求
2. Django Paginator:分页工具,实现数据分页逻辑
3. QuerySet API: 数据库查询集操作(如.all(), .order_by())
4. JSON 数据处理: 解析请求体中的JSON数据
5. 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.countreturn 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()
2. 事务管理: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=111111newlist.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=1newlist.password=111111newlist.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请求
2. Django Paginator:分页工具,实现数据分页逻辑
3. QuerySet API: 数据库查询集操作(如.all(), .order_by())
4. JSON 数据处理: 解析请求体中的JSON数据
5. 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.countreturn 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 idcurrent_menu = Menu.objects.get(id=menu_id)# 获取parent_id的值parent_id = current_menu.parent_id# 判断parent_id是否为0if parent_id == 0:# 如果为0,就把它添加到存储最终的树形结构的空列表中 resultList=[] 顶级resultList.append(menu_obj)else:# 如果不为0,把它的id赋值到parentparent = 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=Nonefor 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.countreturn 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技术栈
- 数据序列化:使用values()直接转换为字典
- 数据库操作:全表查询(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 tokenapi_payload = api_settings.JWT_PAYLOAD_HANDLERapi_encode = api_settings.JWT_ENCODE_HANDLERpayload = api_payload(User)token = api_encode(payload)return JsonResponse({"code": 200,"token": token,"msg": "登录成功"})else:return JsonResponse({"code": 400,"msg": "用户名或密码错误"})
示图: