首页 > Python资料 博客日记
锋哥写一套前后端分离Python权限系统 基于Django5+DRF+Vue3.2+Element Plus+Jwt 视频教程 ,帅呆了~~
2024-09-25 15:00:04Python资料围观55次
本篇文章分享锋哥写一套前后端分离Python权限系统 基于Django5+DRF+Vue3.2+Element Plus+Jwt 视频教程 ,帅呆了~~,对你有帮助的话记得收藏一下,看Python资料网收获更多编程知识
大家好,我是java1234_小锋老师,最近写了一套【前后端分离Python权限系统 基于Django5+DRF+Vue3.2+Element Plus+Jwt 】视频教程,持续更新中,计划月底更新完,感谢支持。
视频在线地址:
打造前后端分离Python权限系统 基于Django5+DRF+Vue3.2+Element Plus+Jwt 视频教程 (火爆连载更新中..)_哔哩哔哩_bilibili
项目介绍
本课程采用主流的Python技术栈实现,Mysql8数据库,Django5后端,redis缓存,DRF框架 ,Vue3.2+Element Plus实现后台管理。基于JWT技术实现前后端分离。
业务功能实现了,登录验证鉴权功能,用户管理(增删改查,角色授权),角色管理(增删改查,权限分配),权限管理(增删改查)。
系统展示
部分代码
import base64
import copy
import hashlib
import json
import os
import random
import uuid
from datetime import datetime
from io import BytesIO
from captcha.image import ImageCaptcha
from django.core import serializers
from django.core.cache import cache
from django.core.paginator import Paginator
from django.core.serializers import serialize
from django.http import JsonResponse, QueryDict
from django.views import View
from rest_framework_jwt.settings import api_settings
from python222_admin import settings
from user.models import SysUser, SysUserSerializer, SysRole, SysMenu, SysMenuSerializer, SysUserRole
# Create your views here.
class LoginView(View):
# 构造菜单树
def buildTreeMenu(self, sysMenuList):
resultMenuList: list[SysMenu] = list()
for menu in sysMenuList:
# 寻找子节点
for e in sysMenuList:
if e.parent_id == menu.id:
if not hasattr(menu, "children"):
menu.children = list()
menu.children.append(e)
# 判断父节点,添加到集合
if menu.parent_id == 0:
resultMenuList.append(menu)
return resultMenuList
def post(self, request):
# data = json.loads(request.body.decode("utf-8"))
username = request.GET.get('username')
password = request.GET.get('password')
code = request.GET.get('code') # 用户填写的验证码
uuid = request.GET.get('uuid')
token = ''
print(password, hashlib.md5(password.encode()).hexdigest())
captcha = cache.get(uuid)
print("captcha", captcha)
if captcha == '' or captcha.lower() != code.lower(): # 判断验证码
return JsonResponse({'code': 500, 'info': '验证码错误!'})
try:
user = SysUser.objects.get(username=username, password=hashlib.md5(password.encode()).hexdigest())
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
# 将用户对象传递进去,获取到该对象的属性值
payload = jwt_payload_handler(user)
# 将属性值编码成jwt格式的字符串
token = jwt_encode_handler(payload)
# roleList = SysRole.objects.raw("select id,role_id from sys_user_role where user_id=" + str(user.id))
roleList = SysRole.objects.raw(
"select id,name from sys_role where id in (select role_id from sys_user_role where user_id=" + str(
user.id) + ")")
menuSet: set[SysMenu] = set()
# roles:str = "" # 当前用户拥有的角色,逗号隔开
roles = ",".join([role.name for role in roleList])
print("roles=", roles)
for row in roleList:
# print("role_id:" + str(row.role_id))
menuList = SysMenu.objects.raw(
"select * from sys_menu where id in (select menu_id from sys_role_menu where role_id=" + str(
row.id) + ")")
for row2 in menuList:
# print(row2.menu_id)
menuSet.add(row2)
menuList: list[SysMenu] = list(menuSet) # set转list
print(menuList)
sorted_menuList = sorted(menuList) # 根据order_num排序
# 构造菜单树
sysMenuList: list[SysMenu] = self.buildTreeMenu(sorted_menuList)
print(sysMenuList)
serializerMenuList: list[SysMenuSerializer] = list()
for sysMenu in sysMenuList:
serializerMenuList.append(SysMenuSerializer(sysMenu).data)
except Exception as e:
print(e)
return JsonResponse({'code': 500, 'info': '用户名或者密码错误!'})
return JsonResponse(
{'code': 200, 'user': SysUserSerializer(user).data, 'token': token, 'roles': roles,
'menuList': serializerMenuList})
class InfoView(View):
def get(self, request):
token = request.META.get('HTTP_AUTHORIZATION')
jwt_decode_handler = api_settings.JWT_DECODE_HANDLER
print("result=", jwt_decode_handler(token))
# 用户角色授权
class GrantRole(View):
def post(self, request):
data = json.loads(request.body.decode("utf-8"))
user_id = data['id']
roleIdList = data['roleIds']
print(user_id, roleIdList)
SysUserRole.objects.filter(user_id=user_id).delete() # 删除用户角色关联表中的指定用户数据
for roleId in roleIdList:
userRole = SysUserRole(user_id=user_id, role_id=roleId)
userRole.save()
return JsonResponse({'code': 200})
class PwdView(View):
def post(self, request):
data = json.loads(request.body.decode("utf-8"))
id = data['id']
oldPassword = data['oldPassword']
newPassword = data['newPassword']
obj_user = SysUser.objects.get(id=id)
if obj_user.password == hashlib.md5(oldPassword.encode()).hexdigest():
obj_user.password = hashlib.md5(newPassword.encode()).hexdigest()
obj_user.update_time = datetime.now().date()
obj_user.save()
return JsonResponse({'code': 200})
else:
return JsonResponse({'code': 500, 'errorInfo': '原密码错误!'})
class SaveView(View):
def post(self, request):
data = json.loads(request.body.decode("utf-8"))
if data['id'] == -1: # 添加
obj_sysUser = SysUser(username=data['username'], password=data['password'],
email=data['email'], phonenumber=data['phonenumber'],
status=data['status'],
remark=data['remark'])
obj_sysUser.create_time = datetime.now().date()
obj_sysUser.avatar = 'default.jpg'
obj_sysUser.password = hashlib.md5("123456".encode()).hexdigest()
obj_sysUser.save()
else: # 修改
obj_sysUser = SysUser(id=data['id'], username=data['username'], password=data['password'],
avatar=data['avatar'], email=data['email'], phonenumber=data['phonenumber'],
login_date=data['login_date'], status=data['status'], create_time=data['create_time'],
update_time=data['update_time'], remark=data['remark'])
obj_sysUser.update_time = datetime.now().date()
obj_sysUser.save()
return JsonResponse({'code': 200})
# 用户状态修改
class StatusView(View):
def post(self, request):
data = json.loads(request.body.decode("utf-8"))
id = data['id']
status = data['status']
user_object = SysUser.objects.get(id=id)
user_object.status = status
user_object.save()
return JsonResponse({'code': 200})
# 重置密码
class PasswordView(View):
def get(self, request):
id = request.GET.get("id")
user_object = SysUser.objects.get(id=id)
user_object.password = hashlib.md5("123456".encode()).hexdigest()
user_object.update_time = datetime.now().date()
user_object.save()
return JsonResponse({'code': 200})
class TestView(View):
def post(self, request):
return JsonResponse({'code': 200, 'info': '测试!'})
# 用户名验证
class CheckView(View):
def post(self, request):
data = json.loads(request.body.decode("utf-8"))
username = data['username']
print("username=", username)
if SysUser.objects.filter(username=username).exists():
return JsonResponse({'code': 500})
else:
return JsonResponse({'code': 200})
# 用户基本操作
class ActionView(View):
def get(self, request):
"""
根据id获取用户信息
:param request:
:return:
"""
id = request.GET.get("id")
user_object = SysUser.objects.get(id=id)
return JsonResponse({'code': 200, 'user': SysUserSerializer(user_object).data})
def delete(self, request):
"""
删除操作
:param request:
:return:
"""
idList = json.loads(request.body.decode("utf-8"))
SysUserRole.objects.filter(user_id__in=idList).delete()
SysUser.objects.filter(id__in=idList).delete()
return JsonResponse({'code': 200})
# 用户信息查询
class SearchView(View):
def post(self, request):
data = json.loads(request.body.decode("utf-8"))
pageNum = data['pageNum'] # 当前页
pageSize = data['pageSize'] # 每页大小
query = data['query'] # 查询参数
print(pageSize, pageNum)
userListPage = Paginator(SysUser.objects.filter(username__icontains=query), pageSize).page(pageNum)
obj_users = userListPage.object_list.values() # 转成字典
users = list(obj_users) # 把外层的容器转为List
for user in users:
userId = user['id']
# roleList = SysRole.objects.raw("select id,user_id,role_id from sys_user_role where user_id=" + str(userId))
roleList = SysRole.objects.raw(
"select id,name from sys_role where id in (select role_id from sys_user_role where user_id=" + str(
userId) + ")")
roles = ",".join([role.name for role in roleList])
roleListDict = []
for role in roleList:
roleDict = {}
roleDict['id'] = role.id
roleDict['name'] = role.name
roleListDict.append(roleDict)
user['roleList'] = roleListDict
total = SysUser.objects.filter(username__icontains=query).count()
return JsonResponse(
{'code': 200, 'userList': users, 'total': total})
class AvatarView(View):
def post(self, request):
data = json.loads(request.body.decode("utf-8"))
id = data['id']
avatar = data['avatar']
obj_user = SysUser.objects.get(id=id)
obj_user.avatar = avatar
obj_user.save()
return JsonResponse({'code': 200})
class ImageView(View):
def post(self, request):
file = request.FILES.get('avatar')
print("file:", file)
if file:
file_name = file.name
suffixName = file_name[file_name.rfind("."):]
new_file_name = datetime.now().strftime('%Y%m%d%H%M%S') + suffixName
file_path = str(settings.MEDIA_ROOT) + "\\userAvatar\\" + new_file_name
print("file_path:", file_path)
try:
with open(file_path, 'wb') as f:
for chunk in file.chunks():
f.write(chunk)
return JsonResponse({'code': 200, 'title': new_file_name})
except:
return JsonResponse({'code': 500, 'errorInfo': '上传头像失败'})
class CaptchaView(View):
def get(self, request):
characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
data = ''.join(random.sample(characters, 4))
print("data", data)
captcha = ImageCaptcha()
imageData: BytesIO = captcha.generate(data)
base64_str = base64.b64encode(imageData.getvalue()).decode()
print(type(base64_str), base64_str)
random_uuid = uuid.uuid4() # 生成一个随机数
print(random_uuid)
cache.set(random_uuid, data, timeout=300) # 存到redis缓存中 有效期5分钟
return JsonResponse({'code': 200, 'base64str': 'data:image/png;base64,' + base64_str, 'uuid': random_uuid})
<template>
<div class="login">
<el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
<h3 class="title">python222 Django后台管理系统</h3>
<el-form-item prop="username">
<el-input
v-model="loginForm.username"
type="text"
size="large"
auto-complete="off"
placeholder="账号"
>
<template #prefix><svg-icon icon="user" /></template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
type="password"
size="large"
auto-complete="off"
placeholder="密码"
>
<template #prefix><svg-icon icon="password" /></template>
</el-input>
</el-form-item>
<el-form-item prop="code">
<el-input
v-model="loginForm.code"
size="large"
auto-complete="off"
placeholder="验证码"
style="width: 63%"
@keyup.enter="handleLogin"
>
<template #prefix><svg-icon icon="validCode" /></template>
</el-input>
<div class="login-code">
<img :src="codeUrl" @click="getCode" class="login-code-img"/>
</div>
</el-form-item>
<el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">记住密码</el-checkbox>
<el-form-item style="width:100%;">
<el-button
size="large"
type="primary"
style="width:100%;"
@click.prevent="handleLogin"
>
<span>登 录</span>
</el-button>
</el-form-item>
</el-form>
<!-- 底部 -->
<div class="el-login-footer">
<span>Copyright © 2013-2022 <a href="http://www.python222.com" target="_blank">python222.com</a> 版权所有.</span>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import requestUtil from '@/utils/request'
import { encrypt, decrypt } from "@/utils/jsencrypt"
import qs from 'qs'
import store from '@/store'
import Cookies from "js-cookie"
import router from "@/router";
import {ElMessage} from 'element-plus'
const codeUrl = ref("");
const loginRef=ref(null);
const loginForm = ref({
username: "",
password: "",
rememberMe: false,
code: "",
uuid: ""
});
const loginRules = {
username: [{ required: true, trigger: "blur", message: "请输入您的账号" }],
password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
code: [{ required: true, trigger: "change", message: "请输入验证码" }]
};
const getCode=async ()=>{
let result=await requestUtil.get("/user/captcha");
console.log(result)
loginForm.value.uuid=result.data.uuid;
codeUrl.value=result.data.base64str;
}
const handleLogin=()=>{
loginRef.value.validate(async (valid)=>{
if(valid){
// 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
console.log("r"+loginForm.value.rememberMe)
if (loginForm.value.rememberMe) {
Cookies.set("username", loginForm.value.username, { expires: 30 });
Cookies.set("password", encrypt(loginForm.value.password), { expires: 30 });
Cookies.set("rememberMe", loginForm.value.rememberMe, { expires: 30 });
} else {
// 否则移除
Cookies.remove("username");
Cookies.remove("password");
Cookies.remove("rememberMe");
}
try{
let result=await requestUtil.post("user/login?"+qs.stringify(loginForm.value));
let data=result.data;
if(data.code==200){
// 生成token
console.log(data.data)
console.log('token:'+data.token)
const currentUser=data.user;
const token=data.token;
const menuList=data.menuList;
console.log("token:",token)
store.commit('SET_TOKEN', token)
console.log("currentUser:"+currentUser)
currentUser.roles=data.roles
store.commit("SET_USERINFO",currentUser);
store.commit("SET_MENULIST",menuList);
router.replace("/index")
}else{
ElMessage.error(data.info);
}
}catch(err){
console.log("error:"+err);
ElMessage.error("服务器出错,请联系管理员!");
}
}else{
console.log("验证失败")
}
})
}
function getCookie() {
const username = Cookies.get("username");
const password = Cookies.get("password");
const rememberMe = Cookies.get("rememberMe");
loginForm.value = {
username: username === undefined ? loginForm.value.username : username,
password: password === undefined ? loginForm.value.password : decrypt(password),
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
};
}
getCookie();
getCode();
</script>
<style lang="scss" scoped>
a{
color:white
}
.login {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
background-image: url("../assets/images/login-background.jpg");
background-size: cover;
}
.title {
margin: 0px auto 30px auto;
text-align: center;
color: #707070;
}
.login-form {
border-radius: 6px;
background: #ffffff;
width: 400px;
padding: 25px 25px 5px 25px;
.el-input {
height: 40px;
input {
display: inline-block;
height: 40px;
}
}
.input-icon {
height: 39px;
width: 14px;
margin-left: 0px;
}
}
.login-tip {
font-size: 13px;
text-align: center;
color: #bfbfbf;
}
.login-code {
width: 33%;
height: 40px;
float: right;
img {
cursor: pointer;
vertical-align: middle;
}
}
.el-login-footer {
height: 40px;
line-height: 40px;
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
color: #fff;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
.login-code-img {
height: 40px;
padding-left: 12px;
}
</style>
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签:
上一篇:区块链-发币 20分钟教程
下一篇:Python Excel 操作全面总结
相关文章
最新发布
- 【Python】selenium安装+Microsoft Edge驱动器下载配置流程
- Python 中自动打开网页并点击[自动化脚本],Selenium
- Anaconda基础使用
- 【Python】成功解决 TypeError: ‘<‘ not supported between instances of ‘str’ and ‘int’
- manim边学边做--三维的点和线
- CPython是最常用的Python解释器之一,也是Python官方实现。它是用C语言编写的,旨在提供一个高效且易于使用的Python解释器。
- Anaconda安装配置Jupyter(2024最新版)
- Python中读取Excel最快的几种方法!
- Python某城市美食商家爬虫数据可视化分析和推荐查询系统毕业设计论文开题报告
- 如何使用 Python 批量检测和转换 JSONL 文件编码为 UTF-8
点击排行
- 版本匹配指南:Numpy版本和Python版本的对应关系
- 版本匹配指南:PyTorch版本、torchvision 版本和Python版本的对应关系
- Python 可视化 web 神器:streamlit、Gradio、dash、nicegui;低代码 Python Web 框架:PyWebIO
- 相关性分析——Pearson相关系数+热力图(附data和Python完整代码)
- Python与PyTorch的版本对应
- Anaconda版本和Python版本对应关系(持续更新...)
- Python pyinstaller打包exe最完整教程
- Could not build wheels for llama-cpp-python, which is required to install pyproject.toml-based proj