首页 > 编程语言 >锋哥写一套前后端分离Python权限系统 基于Django5+DRF+Vue3.2+Element Plus+Jwt 视频教程 ,帅呆了~~

锋哥写一套前后端分离Python权限系统 基于Django5+DRF+Vue3.2+Element Plus+Jwt 视频教程 ,帅呆了~~

时间:2024-09-12 09:54:33浏览次数:13  
标签:code 锋哥 Python Django5 request user import data id

大家好,我是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>

标签:code,锋哥,Python,Django5,request,user,import,data,id
From: https://blog.csdn.net/caoli201314/article/details/142105431

相关文章

  • Python习题 177:设计银行账户类并实现存取款功能
    (编码题)Python实现一个简单的银行账户类BankAccount,包含初始化方法、存款、取款、获取余额等功能。参考答案分析需求如下。Python类BankAccount,用于模拟银行账户的基本功能。该类应包含以下方法:初始化方法:接受两个参数:account_holder(账户持有人的姓名)和balance(账户......
  • 计算机毕业设计必看必学!! 89352 基于python的网上挂号预约系统,原创定制程序, java、P
    摘 要随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,医院当然也不例外。网上挂号预约系统是以实际运用为开发背景,运用软件工程原理和开发方法,采用Python技术构建的一个管理系统。整个开发过程首先对软件系统进......
  • Python的进程池和线程池
    线程池都在一个进程内GIL不适合密集型计算共享进程资源,存在不安全的线程fromconcurrent.futuresimportThreadPoolExecutordeftask(n):returnn*2if__name__=='__main__':withThreadPoolExecutor(max_workers=4)asexecutor:results=......
  • 说下Python中的各个多进程模块之间的区别
    在Python中,主要涉及多进程的模块有multiprocessing、concurrent.futures(使用ProcessPoolExecutor)和os模块。以下是这些模块之间的详细区别:1.multiprocessing模块简介:multiprocessing是Python的标准库之一,提供了创建和管理进程的功能。特点:进程类:提供P......
  • 说下Python中的各个多线程模块之间的区别
    在Python中,涉及多线程的主要模块有threading、thread(在Python2.x中使用)和concurrent.futures。以下是这些模块之间的详细区别:1.threading模块简介:threading是Python的标准库之一,提供了创建和管理线程的高级接口。特点:线程类:提供Thread类,用户可以通......
  • python单例模式
    单例模式(SingletonPattern)是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。Python中实现单例模式有多种方法,以下是几种常见的实现方式:1.使用模块最简单的单例实现是利用Python的模块特性,因为模块在第一次导入时会被初始化,并且后续导入将返回相同的模块对象。......
  • Python中的列表和字典是如何实现的?它们在时间复杂度上有何差异?
    在Python中,列表(list)和字典(dict)是两种非常常用的数据结构,它们的实现方式以及在时间复杂度上的表现有所不同。以下是对它们的实现原理及时间复杂度的详细解释。列表(list)实现动态数组:Python的列表是基于动态数组实现的。这意味着当你向列表中添加元素时,如果当前数组容量不足以......
  • Python中的 GIL是什么?它如何影响多线程?
    GIL(GlobalInterpreterLock)GIL(全局解释器锁)是Python解释器(特别是CPython实现)中的一个机制,用于管理对Python对象的访问。由于Python的内存管理不是线程安全的,GIL确保在任意时刻只有一个线程可以执行Python字节码,从而避免了多个线程同时访问和修改对象造成的数据不一致......
  • python装饰器是什么?有什么作用?
    Python装饰器装饰器是Python中的一种特殊语法结构,允许在运行时动态地修改或增强函数或方法的行为。它们通常用来添加功能,而不需要直接修改原始函数的代码。作用代码重用:装饰器可以封装一些通用的功能,比如日志记录、权限检查、性能监控等,可以在多个函数之间共享这些功能,......
  • Python中的生成器和迭代器有什么区别
    在Python中,生成器(generator)和迭代器(iterator)是两个相关但不同的概念。它们都用于处理可迭代对象,但有一些关键的区别。以下是对这两者的详细解释:迭代器(Iterator)定义:迭代器是实现了__iter__()和__next__()方法的对象。它是一个可以逐个访问其元素的对象。特性:迭代......