Flask学习笔记_异步CMS(五)

2023-11-05


这篇博客是上一篇的后台,使用Vue3+VueCli+VueRouter+Vuex搭建,这个是 学习手册,具体的代码放到了 仓库

1.环境

1.安装nvm

nvm(Node Version Manager)是一个用来管理node版本的工具。首先去nvm下载,然后安装,环境变量自动添加,如果没有手动添加。nvm version查看安装好的版本有哪些。
常用命令

nvm install [version]:安装指定版本的node.js 。
nvm use [version]:使用某个版本的node。
nvm list:列出当前安装了哪些版本的node。
nvm uninstall [version]:卸载指定版本的node。
nvm node_mirror [url]:设置nvm的镜像。
nvm npm_mirror [url]:设置npm的镜像。

2.安装node

以管理员身份运行命令行

nvm install 16.13.0

下载node时就会自动下载npm(Node Package Manager)。然后添加环境变量:C:\Program Files\nodejs
初始化:
在新的项目中,需要先执行npm init初始化,创建一个package.json文件用来保存本项目中用到的包。
安装包:
安装包分为全局安装和本地安装。全局安装是安装在当前node环境中,在可以在cmd中当作命令使用。而本地安装是安装在当前项目中,只有当前这个项目能使用,并且可以通过require引用。安装的方式只有-g参数的区别:

npm install vue   # 本地安装
npm install vue --save   # 本地安装,并且保存到package.json的dependice中
npm install vue --save-dev # 本地安装,并且保存到package.json的dependice-dev中
npm install vue -g   #全局安装
npm install -g @vue/cli  #全局安装vue-cli

本地安装:将安装包放在./node_modules下(运行 npm 命令时所在的目录),如果没有node_modules目录,会在当前执行npm命令的目录下生成node_modules目录。可以通过require()来引入本地安装的包。
全局安装:将安装包放在/usr/local下或者你node的安装目录。可以直接在命令行里使用。
卸载包:

npm uninstall [package]

更新包:

npm update [package]

搜索包:

npm search [package]

项目目录结构

node_modules:本地安装的包的文件夹。
public:项目出口文件。
src:项目源文件:
assets:资源文件,包括字体,图片等。
components:组件文件。
App.vue:入口组件。
main.js:webpack在打包的时候的入口文件。
babel.config.js:es*转低级js语言的配置文件。
package.json:项目包管理文件。

2.使用vue-cli创建项目

npm install -g @vue/cli#全局安装
npm install @vue/cli-service#在项目根目录中安装 vue-cli-service 的本地版本

输入vue --version,如果出现了版本号,说明已经下载完成。
vue create [项目名称]创建项目,然后手动选择vue3,安装完成后按他的提示,cd到目录下,启动服务器,就可以打开工程的vue网页。

npm run server#运行这个项目

3.安装相关插件

在vscode里面安装Vue相关插件:Vetur

  1. Vetur
    Vetur是用来识别.vue文件的,用来给.vue文件中的代码做语法高亮的。用VSCode开发Vue项目,这个插件是必装的!

  2. ESLint
    ESLint是专门针对Vue项目单独开发的一个代码规范的插件。在团队中协作开发中,推荐安装此插件,能统一代码风格。

  3. Vue3 Snippets
    是否有良好的代码自动补全功能,是评判一个开发工具好坏的一个核心要素。而Vue VSCode Snippets则是专门做这个事情的,他根据Vue项目语法,添加了一些代码片段,大大提高了我们编写Vue项目的效率。

  4. Bookmarks
    用于做标记的,在大型项目中,如果经常要在几个地方跳来跳去,那么可以使用Bookmarks来实现跳转。使用方式和快捷命令可以在安装Bookmarks的时候,查看他的介绍。

  5. Bracket Pair Colorizer
    某段代码太长的时候,我们通常是根据代码缩进,来寻找匹配的符号,但是Bracket Pair Colorizer可以通过颜色来进行配对,能节省我们寻找代码的时间,大大提高效率。

  6. Element-Plus组件库:element plus组件库是由饿了么前端团队专门针对vue框架开发的组件库,专门用于电脑端网页的。因为里面集成了很多组件,所以使用他可以非常快速的帮我们实现网站的开发。

npm install element-plus@1.2.0-beta.3 --save

Element-Plus组件的引入:在main.js中引入

import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'

const app = createApp(App)

app.use(ElementPlus)
app.mount('#app')

然后就可以使用Element-Plus组件库开发前端组件。

4.后台CMS开发

1.页面结构

1.app.vue搭建结构

<template>
  <div class="frame">
    <el-container class="frame-container">
      <el-header class="header">
        <a href="/" class="brand"><strong>知了</strong>管理系统</a>
        <div class="header-content">
          <div class="greet">欢迎,周杰伦</div>
          <div class="signout">回到首页</div>
        </div>
      </el-header>
      <el-container>
        <el-aside width="200px" class="aside">
          <el-row class="menu-row">
            <el-col :span="24">
              <el-menu
                default-active="1"
                background-color="#545c64"
                active-text-color="#fff"
                text-color="#ddd"
              >
                <el-menu-item index="1">
                  <template #title>
                    <el-icon></el-icon>
                    <span>首页</span>
                  </template>
                </el-menu-item>

                <el-menu-item index="2">
                  <template #title>
                    <el-icon></el-icon>
                    <span>轮播图</span>
                  </template>
                </el-menu-item>

                <el-menu-item index="3">
                  <template #title>
                    <el-icon></el-icon>
                    <span>帖子管理</span>
                  </template>
                </el-menu-item>

                <el-menu-item index="4">
                  <template #title>
                    <el-icon></el-icon>
                    <span>评论管理</span>
                  </template>
                </el-menu-item>

                <el-menu-item index="5">
                  <template #title>
                    <el-icon></el-icon>
                    <span>用户管理</span>
                  </template>
                </el-menu-item>
              </el-menu>
            </el-col>
          </el-row>
        </el-aside>
        <el-container>
          <el-main class="main">
            这里放网页内容部分
          </el-main>
          <el-footer class="footer">这是Footer</el-footer>
        </el-container>
      </el-container>
    </el-container>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

<style scoped>
.frame-container {
  height: 100vh;
}
.header {
  height: 60px;
  background: #00a65a;
  display: flex;
}

.header .brand {
  width: 200px;
  margin-left: -20px;
  background-color: #008d4c;
  font-size: 20px;
  color: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
}
.header .header-content {
  flex: 1;
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-left: 20px;
  color: #fff;
}

.header-content .signout {
    cursor: pointer;
  }

.aside {
  background-color: #545c64;
}

.aside .el-menu .is-active {
  background-color: #434a50 !important;
}

.footer {
  background: gray;
}
</style>

<style scoped>
.el-menu{
  border-right: none;
}
</style>

<style>
* {
  margin: 0;
  padding: 0;
  border: 0;
  text-decoration: none;
  vertical-align: baseline;
}
</style>

2.element-icon组件的使用

1.使用element的icon组件,先要安装

 npm install @element-plus/icons-vue --save

2.然后在script中导入

<script>
import {House,PictureRounded,Postcard,Comment,User} from "@element-plus/icons"
export default {
  name: "App",
  components: {House,PictureRounded,Postcard,Comment,User}
};
</script>

3.合适位置引用使用

<el-icon><House /></el-icon>
<el-icon><PictureRounded /></el-icon>
<el-icon><Postcard /></el-icon>
<el-icon><Comment /></el-icon>
<el-icon><User /></el-icon>

3.iconfont组件的使用

更多的icon可以使用阿里巴巴的iconfont
1.在里面添加自己需要的icon到项目,然后点击Font class,复制链接,到index.html里面添加这个css文件链接

<link rel="stylesheet" href="//at.alicdn.com/t/c/font_4197214_rad25hwlak.css"/>

2.复制icon代码,然后在合适的地方引用

2.使用Vue-router实现页面跳转

1.安装

在工程目录下

npm install vue-router@4

2.页面跳转

1.在components目录下建自己的vue文件(Home.vue)

<template>
  <div id="home">
    <h1>首页</h1>
  </div>
</template>

<script>
export default {
    name: "HomeComponent",
}
</script>

<style scoped>

</style>

2.在src目录下建一个router.js写路由管理(@代表src)

import { createRouter,createWebHashHistory } from "vue-router";
import HomeComponent from "@/components/Home.vue";
const routes = [{path:"/",component:HomeComponent,name:"home"}]
const router=createRouter({history:createWebHashHistory(),routes})
export default router;

3.在main.js中把路由绑定到app上

import router from"@/router"
app.use(router);

4.在app.vue的menu组件里面添加属性router=true

:router="true"

5.在app.vue需要跳转的组件里添加路由信息

<el-menu-item index="1" :route="{name:'home'}">

6.在跳转链接需要加载的地方加上

<router-view></router-view>

3.JWT鉴权

1.安装

pip install flask-jwt-extended

2.在exts里面导入

from flask_jwt_extended import JWTManager
jwt = JWTManager()

3.在config里面设置钥和过期时间

SECRET_KEY="FASDFNMLKSDF"
JWT_ACCESS_TOKEN_EXPIRES=timedelta(days=7)

4.在app.py里面init

from exts import jwt
jwt.init_app(app)

5.在登录的视图函数中判断是否是员工,即有访问cms的权限,保存jwt生成的token,返回给前端

from flask_jwt_extended import create_access_token
token =""
if user.is_staff():
    token=create_access_token(identity=user.id)
 return restful.ok(data={'token':token})

5.在登录的js里面,判断保存token,如果后端返回了这个值,就把他保存到应用》本地存储空间》JWT_TOKEN_KEY

 success: function (result){
        if(result['code'] == 200){
          localStorage.setItem("JWT_TOKEN_KEY", token);}

6.再下一次访问cms时,会判断前端是否带有JWT_TOKEN_KEY值,在apps/cmsapi/views.py里面写cms的首页视图函数,并注册到app

from flask import Blueprint#views.py
from utils import restful
from flask_jwt_extended import jwt_required,get_jwt_identity
bp=Blueprint("cmsapi",__name__,url_prefix="/cmsapi/")
@bp.get('/')
@jwt_required()
def index():
    identity=get_jwt_identity()
    return restful.ok(message="成功",data={"identity": identity})
from .views import bp as cmsapi_bp#__init__.py
from apps.cmsapi import cmsapi_bp#app.py
app.register_blueprint(cmsapi_bp)

4.SerializerMixin实现ORM模型序列化

1.安装

pip install SQLAlchemy-serializer

2.在UserModel里面继承并确定要返回的字段

from sqlalchemy_serializer import SerializerMixin
class UserModel(db.Model,SerializerMixin):
serialize_rules=("-_password",)
serialize_only=("id",'email','username','avatar','signature','join_time','is_staff','is_active',)#这样写可以避免循环序列化

3.在登录的视图函数里,当登录成功时,返回如下

return restful.ok(data={'token':token,"user":user.to_dict()})

4.当成功返回到客户端时,可以在js里面接收到这些信息

success: function (result){
        if(result['code'] == 200){
          var token = result['data']['token'];
          var user = result['data']['user'];
          localStorage.setItem("JWT_TOKEN_KEY", token);
          localStorage.setItem("USER_KEY", JSON.stringify(user));
          console.log(user);
          window.location = "/"
        }else{
          alert(result['message']);
        }
      }

5.CMS访问权限

1.首先在src/utils/auth.js里面对服务器发来的数据进行验证

const USER_KEY = "USER_KEY"
const TOKEN_KEY = "JWT_TOKEN_KEY"

class Auth{
  constructor(){
    this.token = null
    this.user = null
    this.token = localStorage.getItem(TOKEN_KEY)
    const userJson = localStorage.getItem(USER_KEY)
    if(userJson){
      this.user = JSON.parse(userJson)
    }
  }

  static getInstance(){
    if(!this._instance){
      this._instance = new Auth()
    }
    return this._instance
  }
  
  setUserToken(user,token){
    this.user = user
    this.token = token
    localStorage.setItem(USER_KEY,JSON.stringify(user))
    localStorage.setItem(TOKEN_KEY,token)
  }

  clearUserToken(){
    this.user = null;
    this.token = null;
    localStorage.removeItem(USER_KEY)
    localStorage.removeItem(TOKEN_KEY)
  }

  get is_authed(){
    if(this.user && this.token){
      return true
    }else{
      return false
    }
  }

  get is_staff(){
      if(!this.is_authed){
        return false;
      }
      if(this.user.is_staff){
        return true;
      }
      return false;
  }
}
export default Auth.getInstance()

2.然后在main.js里将上面的身份验证导入到app,变为全局变量$auth

import auth from "@/utils/auth"
app.config.globalProperties.$auth=auth;

3.在app.vue里面利用vue的生命周期里的mounted进行验证并返回首页

mounted(){
  if(!this.$auth.is_staff){
    window.location='http://127.0.0.1:5000';
  }
},

6.axios网络请求库

1.下载

npm install axios --save
npm install qs --save

2.在src/utils/auth.js里面对axios进行封装

import axios from "axios"
import auth from "./auth"
import qs from "qs";

// http://www.zlkt.net
// const SERVER_HOST = "http://127.0.0.1:5000"
// window.location.origin

// const SERVER_HOST = window.location.origin;

// const SERVER_HOST = process.env.VUE_APP_SERVER_HOST


// 配置文件
// .env
// .env.[mode]

// mode:development、test、production

// npm run server:用的是development模式
// npm run build:默认用的是production模式
// npm run build -- --mode [模式,比如:development]来指定具体的模式

// 不同的模式,会读取对应模式下的配置参数
// development模式:.env.development配置文件
// production模式:.env.development配置文件

// 在配置文件中,只能有三种类型的配置项:NODE_ENV,BASE_URL,VUE_APP_开头的
// 比如:VUE_APP_SERVER_HOST

// 配置项中,只能是字符串,不能填一些js代码。比如window.location.origin
// 这样去写,实际上是一个"window.location.origin"

class Http {
	constructor() {
		if(process.env.NODE_ENV == 'production'){
			this.server_host = window.location.origin;
		}else{
			this.server_host = "http://127.0.0.1:5000"
		}
		this.http = axios.create({
			baseURL: this.server_host + "/cmsapi",
			timeout: 1000*60
		});

		// 请求之前的拦截器,用来设置JWT
		this.http.interceptors.request.use(config => {
			const token = auth.token
			if (token) {
				config.headers.common.Authorization = "Bearer " + token
			}
			return config
		})

		// 响应拦截
		this.http.interceptors.response.use(response => {
			return response.data;
		})
	}

	_post(url, data){
		return this.http.post(url, qs.stringify(data));
	}

	addBanner(data){
		const url = "/banner/add"
		return this._post(url, data);
	}

	getBannerList(){
		const url = "/banner/list"
		return this.http.get(url);
	}

	deleteBanner(banner_id){
		const url = "/banner/delete"
		return this._post(url, {"id": banner_id})
	}

	editBanner(data){
		const url = "/banner/edit"
		return this._post(url, data);
	}

	getPostList(page){
		const url = "/post/list?page=" + (page?page:1)
		return this.http.get(url);
	}

	deletePost(post_id){
		const url = "/post/delete"
		return this._post(url, {"id": post_id})
	}

	getCommentList(){
		const url = "/comment/list"
		return this.http.get(url)
	}

	deleteComment(comment_id){
		const url = "/comment/delete"
		return this._post(url, {"id": comment_id})
	}

	getUserList(page){
		const url = "/user/list?page=" + (page?page:1)
		return this.http.get(url)
	}

	activeUser(user_id, is_active){
		const url = "/user/active"
		return this._post(url, {"id": user_id, "is_active": is_active})
	}

	getBoardPostCount(){
		const url = "/board/post/count"
		return this.http.get(url);
	}

	getDay7PostCount(){
		const url = "/day7/post/count"
		return this.http.get(url)
	}
}

export default new Http()

3.在main.js里面绑定到全局变量上

import http from "@/utils/http"
app.config.globalProperties.$http=http;

7.轮播图

1.在banner.vue里面写前端显示,css和js
2.写点击上传的view和form验证,config里面写图片存的地址

3.跨域请求

1.安装flask-cors

pip install -U flask-cors

2.exts导入

from flask_cors import CORS
cors=CORS()

3.初始化到app

from exts import cors
cors.init_app(app,resources={r"/cmsapi/*":{"origins":"*"}})#9.cors绑定到app
csrf.exempt(cmsapi_bp)#这个蓝图的请求不进行crsf验证
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Flask学习笔记_异步CMS(五) 的相关文章

随机推荐

  • 最容易理解的JavaScript解决约瑟夫环问题的方式之一

    这种方式虽然效率不是最高的 但绝对是最容易理解的思路之一 function ysf flag stayNum allNum let arr let start 1 for let i 1 i lt allNum i arr push i 当
  • 做爱做的事,做有快感的事

    还是不发首页了 最近没规划 需要缓一缓 因为发首页还是要符合几点要求的 所以就先停停 不过文章还是得写 本来十一点多就写好了 没想到洗个澡就过了十二点 今天就更像聊天了 上一篇说到拖延症 最后留下了一个尾巴 就是怎么找到不会发生拖延症的事去
  • 【Git】(四)子模块

    1 增加子模块 进入准备添加子模块所在的目录 例如library git submodule add b 1 0 0 0 git gitee com sunriver2000 SubModule git 参数 b用于指定子模块分支 2 更新
  • 刷脸支付每个人的脸都具有唯一性无法复制

    移动支付时代 手机成为承载资金的介质 人人手机里有支付宝或者微信支付 但如果手机一旦丢失 不法分子破解了用户密码 那么资金安全也面临威胁 而刷脸支付的第一大优势就在于保证用户资金安全 因为在整个支付过程中 用户完全不用打开手机和自己的资金账
  • [游戏开发][Shader]GLSLSandBox转Unity-CG语言

    官网 GLSL Sandbox Galleryhttps glslsandbox com 屏幕坐标计算 fragCoord与 ScreenParams mat2矩阵转换 vec2向量 在GLSL里mat2 a b c d 函数返回vec2
  • yolov3之数据集预处理

    目录 txt标签文件的说明 将jpg与txt文件分开 txt生成xml标签文件 xml标签详解 xml标签生成txt txt标签文件的说明 获取到的数据集是这样的 需要转换为VOC格式 其实就是将txt转换为xml文件 打开txt文件可以看
  • 在线代码编辑器:Monaco Editor

    monaco editor是微软开源的一款web版代码编辑器 它支持智能提示 代码高亮 代码格式化 Monaco Editor是为VS Code提供支持的代码编辑器 运行在浏览器环境中 编辑器提供代码提示 智能建议等功能 供开发人员远程更方
  • 2013年9月10日星期二(DEMO8_6矩阵)

    首先设置了2个矩阵 1 把所有的点存储为1 2矩阵 typedef struct MATRIX1X2 TYP float M 2 MATRIX1X2 MATRIX1X2 PTR M X Y 2把所有变换矩阵采用3 2矩阵 typedef s
  • 带你玩转kubernetes-k8s(第21篇:k8s-深入掌握Pod-初始化容器、Pod滚动升级)

    上节内容的错误 还请大家不要太在意 后面我们会解决的 理解Job的作用 概念就可以了 下面我们进入正题 Init Container 初始化容器 在很多应用场景中 应用在启动之前都需要进行如下初始化操作 等待其他关联组件正确运行 例如数据库
  • Gitbash 无法显示中文

    GitBash gt 右键 gt options gt 左侧text 设置locale zh cn 设置Character set GBK save gt apply GitBash输入 systeminfo看能否正常显示
  • 几种C/C++语言安全检测工具介绍

    转自新浪微博http www vckbase com index php wv 1635 针对C C 语言安全漏洞的分析检测也出现了大量的工具 按照不同的机理主要分为以下几类 如表所示 分析类型 机理 分析工具 备注 静态分析 预处理 Fo
  • ## Hive分区、桶、与倾斜

    Hive的分区 1 在Hive Select 查询中一般会扫描整个表内容 会消耗很多时间做没必要的工作 有时候查询 只需要扫描表中关心的一部分数据 因此建表时引入partition概念 2 分区表指的是在创建表时指定的partition的分
  • 数据库查询最近N天数据

    查询最近7天数据 1 查询最近7天订单金额 用到了虚表和UNION ALL的知识 其中 price是要查询的数据 orders是表名 IFNULL b price 0 是指b price如果值为空 则将空值设置为0 SELECT a cli
  • Java版手写数字(0~9)BP神经网络识别

    MNIST的样本集太无趣 连图片都看不到 也无法用人手进行输入 所以 基于BP神经网络的理论知识 参见数据挖掘黑书212页起 讲得甚好 纯手写了一版带训练和测试的小玩具 Java语言 效果如下 代码已上传github https githu
  • 多项式回归(非线性回归)的python代码实现

    1 概述 在解决回归问题中 很多数据集中输入空间与输出空间并非完全呈线性关系 使用线性回归无法解决此类问题 为了解决存在非线性关系的数据集的回归问题 需要进行多项式回归 但sklearn并未提供多项式回归模型的类 多项式回归使用的还是线性回
  • 字节的对齐方式

    VC对结构的存储的特殊处理确实提高CPU存储变量的速度 但是有时候也带来了一些麻烦 我们也屏蔽掉变量默认的对齐方式 自己可以设定变量的对齐方式 重要规则 1 复杂类型中各个成员按照它们被声明的顺序在内存中顺序存储 第一个成员的地址和整个类型
  • 【k8s】k8s部署网络插件Calico、创建网络策略

    一 简介 01 calico简介 calico官网 flannel实现的是网络通信 calico的特性是在pod之间的隔离 通过BGP路由 但大规模端点的拓扑计算和收敛往往需要一定的时间和计算资源 纯三层的转发 中间没有任何的NAT和ove
  • String、StringBuffer与StringBuilder之间区别

    String StringBuffer StringBuilder String的值是不可变的 这就导致每次对String的操作都会生成新的String对象 不仅效率低下 而且浪费大量优先的内存空间 StringBuffer是可变类 和线程
  • Σ-Δ ADC的高精度数模转化,是如何实现的?

    以前接触过 ADC24位采样芯片 一直对其原理没有搞清楚 最近看到有对其原理讲解的文章 因此收集下来作为参考 我们在了解Delta Sigma ADC原理之前 先明确几个概念 1 量化噪声 下图中 蓝色斜线是连续的模拟信号 阶梯状波形是经过
  • Flask学习笔记_异步CMS(五)

    Flask学习笔记 异步CMS 五 1 环境 1 安装nvm 2 安装node 2 使用vue cli创建项目 3 安装相关插件 4 后台CMS开发 1 页面结构 1 app vue搭建结构 2 element icon组件的使用 3 ic