flask实现简易图书管理系统
项目结构
技术选型
flask 做后端, 提供数据和渲染html
暂时没有提供mysql, 后续会更新操作mysql和样式美化的版本
起一个flask服务
flask是python的一个web框架, 下面演示如何提供http接口, 并返回json数据
main.py
# flask创建http接口
from flask import Flask, request, jsonify,render_template
# 支持flask跨域
from flask_cors import CORS
# 创建flask服务
app = Flask(__name__)
CORS(app, resources=r'/*') # 注册CORS, "/*" 允许访问域名所有api # 首页
@app.route('/',methods=['get'])
def index():# 自动在templates里找对应名称的文件return jsonify({"msg":"hello"})if __name__ == "__main__":# 运行web服务app.run(host='0.0.0.0', port=10086)
此时打开终端, 运行
python main.py
打开浏览器, 输入 http://localhost:10086/
渲染模板
flask可以渲染html文件(自动往项目根目录的templates里找), 并往里面填数据
main.py
# flask创建http接口
from flask import Flask, request, jsonify,render_template
# 支持flask跨域
from flask_cors import CORS
# 创建flask服务
app = Flask(__name__)
CORS(app, resources=r'/*') # 注册CORS, "/*" 允许访问域名所有api # 首页
@app.route('/',methods=['get'])
def index():# 自动在templates里找对应名称的文件return render_template('index.html',msg="hello world")if __name__ == "__main__":# 运行web服务app.run(host='0.0.0.0', port=10086)
index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body>{{msg}}
</body>
</html>
浏览器
用对象数组来存放图书数据
main.py
通过模板渲染传递books到html里
# flask创建http接口
from flask import Flask, request, jsonify,render_template
# 支持flask跨域
from flask_cors import CORS
# 创建flask服务
app = Flask(__name__)
CORS(app, resources=r'/*') # 注册CORS, "/*" 允许访问域名所有api # 暂时代替数据库
books = [{"id":'1',"name":"hello world","author":"迭名","desc": "程序员入门第一本书","price": 11.99},{"id":'2',"name":"0基础学it","author":"xx程序员","desc": "某培训机构精心出品教程","price": 99.98},
]# 首页
@app.route('/',methods=['get'])
def index():# 自动在templates里找对应名称的文件return render_template('index.html',books=books)if __name__ == "__main__":# 运行web服务app.run(host='0.0.0.0', port=10086)
index.html
html接收flask后端传来的数据, 渲染到table里
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<!-- 加样式,居中 -->
<style>* {margin: 0 auto;}
</style><body><br><table border="1"><thead><tr><th>书名</th><th>作者</th><th>描述</th><th>价格</th><th>操作</th></tr></thead><tbody>{% for book in books %} {# 遍历 books 变量 #}<tr id={{book.id}}><th>{{book.name}}</th><th>{{book.author}}</th><th>{{book.desc}}</th><th>{{book.price}}</th><th><button id={{book.id}}>删除</button><a href='http://localhost:10086/uptbook?id={{book.id}}'>修改</a></th></tr>{% endfor %} {# 使用 endfor 标签结束 for 语句 #}</tbody></table><br>
</body></html>
查看效果
添加图书
使用a标签请求flask后端, flask后端返回html模板, 实现跳转添加页面(add.html)
这里add.html是在book下, 这是因为如果还有别的服务(比如用户的crud), 可以通过不同文件夹区分模块
添加两个接口, 我们的id就用book对象在books数组里的下标(索引/序号), 添加就直接append添加到books数组的末尾
# 跳转添加页面
@app.route('/addbook',methods=['get'])
def addbook_html():# 自动在templates里找对应名称的文件return render_template('book/add.html')# 添加
@app.route('/addbook',methods=['post'])
def addbook(): # 获取json数据book = request.get_json() book['id']= str(len(book)-1) books.append(book)return jsonify({"books":books})
main.py
# flask创建http接口
from flask import Flask, request, jsonify,render_template
# 支持flask跨域
from flask_cors import CORS
# 创建flask服务
app = Flask(__name__)
CORS(app, resources=r'/*') # 注册CORS, "/*" 允许访问域名所有api # 暂时代替数据库
books = [{"id":'1',"name":"hello world","author":"迭名","desc": "程序员入门第一本书","price": 11.99},{"id":'2',"name":"0基础学it","author":"xx程序员","desc": "某培训机构精心出品教程","price": 99.98},
]# 首页
@app.route('/',methods=['get'])
def index():# 自动在templates里找对应名称的文件return render_template('index.html',books=books)# 跳转添加页面
@app.route('/addbook',methods=['get'])
def addbook_html():# 自动在templates里找对应名称的文件return render_template('book/add.html')# 添加
@app.route('/addbook',methods=['post'])
def addbook(): # 获取json数据book = request.get_json() # 用数组下标表示idbook['id']= str(len(book)-1) # 添加到books末尾books.append(book)return jsonify({"books":books})if __name__ == "__main__":# 运行web服务app.run(host='0.0.0.0', port=10086)
index.html
我们使用axios(js的一个库)来发送http请求
<!-- 引入axios发送请求给后端 -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
发送请求前, 通过input框的value获取数据, 然后axios发送post请求, 并传递一个json对象给后端
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><form id="form"><lable>书名</lable><input type="text" name="book-name" id="book-name"><label>作者</label><input type="text" name="book-author" id="book-author"><label>描述</label><input type="text" name="book-desc" id="book-desc"><label>价格</label><input type="text" name="book-price" id="book-price"><button type="submit">提交</button></form><!-- 引入axios发送请求给后端 --><script src="https://unpkg.com/axios/dist/axios.min.js"></script><script>const addform = document.querySelector("#form")const bookName = document.querySelector("#book-name")const bookDesc = document.querySelector("#book-desc")const bookAuthor = document.querySelector("#book-author")const bookPrice = document.querySelector("#book-price")addform.addEventListener("submit", function (e) {e.preventDefault();// console.log(bookName.value);// 发送请求给后端axios.post('http://localhost:10086/addbook',// 传递json数据给后端{name: bookName.value,author: bookAuthor.value,desc: bookDesc.value,price: bookPrice.value})// axios请求完成后.then((res) => {// 后端处理完请求,axios拿到的结果console.log(res);alert('添加成功')// 跳转首页window.location.href = 'http://localhost:10086/'})})</script>
</body></html>
查看效果
删除图书
我们通过axios发送delete请求给后端, 同时传递id, 后端遍历books, 找到对应id的元素下标, 然后删除
main.py
# flask创建http接口
from flask import Flask, request, jsonify,render_template
# 支持flask跨域
from flask_cors import CORS
# 创建flask服务
app = Flask(__name__)
CORS(app, resources=r'/*') # 注册CORS, "/*" 允许访问域名所有api # 暂时代替数据库
books = [{"id":'1',"name":"hello world","author":"迭名","desc": "程序员入门第一本书","price": 11.99},{"id":'2',"name":"0基础学it","author":"xx程序员","desc": "某培训机构精心出品教程","price": 99.98},
]# 首页
@app.route('/',methods=['get'])
def index():# 自动在templates里找对应名称的文件return render_template('index.html',books=books)# 跳转添加页面
@app.route('/addbook',methods=['get'])
def addbook_html():# 自动在templates里找对应名称的文件return render_template('book/add.html')# 添加
@app.route('/addbook',methods=['post'])
def addbook(): # 获取json数据book = request.get_json() # 用数组下标表示idbook['id']= str(len(book)-1) # 添加到books末尾books.append(book)return jsonify({"books":books})# 删除
@app.route('/delete',methods=['delete'])
def delbook():id = request.args.get('id')# 下标index = -1# 遍历,找到id相同的元素for i in range(len(books)):if books[i]['id'] == id:# 记录元素下标index = i# id不是-1表示有找到要删除的元素if i != -1:# 删除books.remove(books[index])return jsonify({'books': books})else:return jsonify({'books': books})if __name__ == "__main__":# 运行web服务app.run(host='0.0.0.0', port=10086)
index.html
我们在渲染table的时候, 将每行(tr标签)的id设为book的id, 删除时, 可以通过tr的id获取要删除的book的id, 实现删除特定的book
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<!-- 加样式,居中 -->
<style>* {margin: 0 auto;text-align: center;}
</style><body><br><table border="1"><thead><tr><th>书名</th><th>作者</th><th>描述</th><th>价格</th><th>操作</th></tr></thead><tbody>{% for book in books %} {# 遍历 books 变量 #}<tr id={{book.id}}><th>{{book.name}}</th><th>{{book.author}}</th><th>{{book.desc}}</th><th>{{book.price}}</th><th><button id={{book.id}}>删除</button><a href='http://localhost:10086/uptbook?id={{book.id}}'>修改</a></th></tr>{% endfor %} {# 使用 endfor 标签结束 for 语句 #}</tbody></table><br><a href="http://localhost:10086/addbook">添加图书</a><!-- axios,可以发送请求给后端 --><script src="https://unpkg.com/axios/dist/axios.min.js"></script><script>// 按钮const btns = document.querySelectorAll('th > button')// 遍历btns.forEach((b) => {console.log(b.id);// 给按钮添加click事件b.addEventListener('click', function (e) {// todo 弹出确认框,是否删除// 删除axios.delete(("http://localhost:10086/delete?id=" + b.id)).then((res) => {if (res.status == 200 && res.data) {// 刷新页面location.reload();alert('删除成功')} else {alert('删除失败')}})})})</script>
</body></html>
查看效果
修改图书信息
前端点击修改后跳转修改页面
<a href='http://localhost:10086/uptbook?id={{book.id}}'>修改</a>
main.py
# flask创建http接口
from flask import Flask, request, jsonify,render_template
# 支持flask跨域
from flask_cors import CORS
# 创建flask服务
app = Flask(__name__)
CORS(app, resources=r'/*') # 注册CORS, "/*" 允许访问域名所有api # 暂时代替数据库
books = [{"id":'1',"name":"hello world","author":"迭名","desc": "程序员入门第一本书","price": 11.99},{"id":'2',"name":"0基础学it","author":"xx程序员","desc": "某培训机构精心出品教程","price": 99.98},
]# 首页
@app.route('/',methods=['get'])
def index():# 自动在templates里找对应名称的文件return render_template('index.html',books=books)# 跳转添加页面
@app.route('/addbook',methods=['get'])
def addbook_html():# 自动在templates里找对应名称的文件return render_template('book/add.html')# 添加
@app.route('/addbook',methods=['post'])
def addbook(): # 获取json数据book = request.get_json() # 用数组下标表示idbook['id']= str(len(book)-1) # 添加到books末尾books.append(book)return jsonify({"books":books})# 删除
@app.route('/delete',methods=['delete'])
def delbook():id = request.args.get('id')# 下标index = -1# 遍历,找到id相同的元素for i in range(len(books)):if books[i]['id'] == id:# 记录元素下标index = i# id不是-1表示有找到要删除的元素if i != -1:# 删除books.remove(books[index])return jsonify({'books': books})else:return jsonify({'books': books})# 跳转修改页面
@app.route('/uptbook',methods=['get'])
def uptbook_html():id = request.args.get('id') book = {}for b in books: if b['id'] == id:book = breturn render_template('book/update.html',book=book)# 修改
@app.route('/uptbook',methods=['patch'])
def uptbook():id = request.args.get('id') book = request.get_json() index = -1for i in range(len(books)): if books[i]['id'] == id:index = iif index == -1:return jsonify({"books":books})else: if(book['name']!=None):books[index]['name'] = book['name']if(book['author']!=None):books[index]['author'] = book['author']if(book['desc']!=None):books[index]['desc'] = book['desc']if(book['price']!=None):books[index]['price'] = book['price']return jsonify({"books":books}) if __name__ == "__main__":# 运行web服务app.run(host='0.0.0.0', port=10086)
update.html
和添加图书页面基本相同
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><!-- 自定义属性,值为book.id --><form id="form" data-id={{book.id}}><lable>书名</lable><input type="text" name="book-name" value={{book.name}} id="book-name"><label for="">作者</label><input type="text" name="book-author" value={{book.author}} id="book-author"><label for="">描述</label><input type="text" name="book-desc" value={{book.desc}} id="book-desc"><label for="">价格</label><input type="text" name="book-price" value={{book.price}} id="book-price"><button type="submit">提交</button></form><script src="https://unpkg.com/axios/dist/axios.min.js"></script><script>const uptform = document.querySelector("#form")const bookName = document.querySelector("#book-name")const bookDesc = document.querySelector("#book-desc")const bookAuthor = document.querySelector("#book-author")const bookPrice = document.querySelector("#book-price")// 自定义属性 const id = uptform.dataset.iduptform.addEventListener("submit", function (e) {e.preventDefault();// console.log(bookName.value);// 发送请求给后端axios.patch(("http://localhost:10086/uptbook?id=" + id), {name: bookName.value,author: bookAuthor.value,desc: bookDesc.value,price: bookPrice.value}).then((res) => {console.log(res);alert('修改成功')// 跳转回首页window.location.href = 'http://localhost:10086/'})})</script>
</body></html>
查看效果
完结, 恭喜
相关文章:

flask实现简易图书管理系统
项目结构 技术选型 flask 做后端, 提供数据和渲染html 暂时没有提供mysql, 后续会更新操作mysql和样式美化的版本 起一个flask服务 flask是python的一个web框架, 下面演示如何提供http接口, 并返回json数据 main.py # flask创建http接口 from flask import Flask, request, jso…...
2021 年全国大学生物联网设计竞赛(华为杯)全国总决赛获奖名单
由全国高等学校计算机教育研究会主办,上海交通大学承办,华为技术有限 公司协办,中国电信天翼物联、中国移动中移物联网、霍尼韦尔 Tridium、CSA 联盟、新大陆、德州仪器 (TI)、百度、机械工业出版社华章公司联合支持的 2021 全国大学生物联网…...

操作系统复习2.3.5-管程
引入管程 PV操作困难,容易书写出错,引入管程,作为一种高级同步机制 组成 局限于管程的共享数据结构说明对该数据结构进行操作的一组过程对局部于管程的共享数据结构设置初始值的语句管程有一个名字 基本特征 局限于管程的数据只能被局限…...
List Set Map Queue Deque 之间的区别是什么?
List Set Map Queue Deque 之间的区别是什么? 1. Java 集合框架有那些接口?2. List Set Map Queue Deque 之间的区别是什么? 1. Java 集合框架有那些接口? List、Set、Map、Queue、Deque 2. List Set Map Queue Deque 之间的区别…...
unity行为决策树实战详解
一、行为决策树的概念 行为决策树是一种用于游戏AI的决策模型,它将游戏AI的行为分解为一系列的决策节点,并通过节点之间的连接关系来描述游戏AI的行为逻辑。在行为决策树中,每个节点都代表一个行为或决策,例如移动、攻击、逃跑等…...

Spring学习记录
目录 bean的单例与多例 设置 工厂模式的三种形态 简单工厂模式 代码: 运行结果: 总结: 工厂模式 代码: 运行结果: 总结: 抽象工厂模式 代码: 运行结果: 总结: …...
模板方法-
定义:又叫模板模式,是指定义一个算法骨架,并允许子类为其中的一个或多个步骤提供实现。 适用场景: 1、一次性实现一个算法不变的部分,并将可变的行为留给子类来实现 2、各子类中公共的行为被提取出来并集中到一个公共的父类中,从而避免代码重复 优点…...

[Kubernetes] - RabbitMQ学习
1.消息队列 消息: 在应用间传送的数据队列,先进先出 1.2. 作用 好处:解耦, 容错,削峰坏处:降低系统可用性,系统复杂度提高,一致性问题; RabbitMQ组成部分:…...

swagger页面 doc.html出不来,swagger-ui/index.html能出来
swagger页面 doc.html出不来,swagger-ui/index.html能出来。前前后后折腾了很久,jar包冲突,jar包版本,添加路径啥的都弄了,就是出不来。 后来全局搜索“doc.html”页面发现能出来的项目能搜到这个页面: 定…...

IEEE802.3和IEEE802.11的分类(仅为分类)
IEEE802.3标准 IEEE802.3:10兆以太网 ●10Base-5 使用粗同轴电缆,最大网段长度为500m,基带传输方法; ●10Base-2 使用细同轴电缆,最大网段长度为185m,基带传输方法; ●10Base&am…...
c# cad二次开发通过获取excel数据 在CAD绘图,将CAD属性导出到excel
c# cad二次开发通过获取excel数据 在CAD绘图,将CAD属性导出到excel using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Runtime; using System; using System.Collections.Generic; using System.Linq; us…...
LLM之高性能向量检索库
LLM向量数据库 高性能向量检索库milvus简介安装调用 faiss简介安装调用 高性能向量检索库 milvus 简介 Milvus 是一个开源的向量数据库引擎,旨在提供高效的向量存储、检索和分析能力。它被设计用于处理大规模的高维向量数据,常用于机器学习、计算机视觉…...
实体类注解
目录 一、TableField注解 二、TableId注解 三、Table注解 四、TableLogic注解 五、Getter与Setter注解 六、EqualsAndHashCode注解 七、Accessors注解 一、TableField注解 Data NoArgsConstructor //空参构造方法 AllArgsConstructor //全参构造方法 TableName("t…...
常见数据结构种类
常见数据结构种类 数据存储的常用结构有:栈、队列、数组、链表和红黑树 a.队列(queue) – 先进先出,后进后出。 – 场景:各种排队。叫号系统。 – 有很多集合可以实现队列。 b.栈(stack) – …...

linux高级---k8s中的五种控制器
文章目录 一、k8s的控制器类型二、pod与控制器之间的关系三、状态与无状态化对特点四、Deployment1、Deployment的资源清单文件2、在配置清单中调用deployment控制器3、镜像更新4、金丝雀发布5、删除Deployment 五、Statefulset六、DaemonSet1、daemonset的资源清单文件2、在配…...

记一次udp服务性能优化经历
目录 概述磁盘io网络io减少重复计算减少内存复制减少互斥锁 概述 手上有个go项目,接收udp信息(主要是syslog和snmp trap)并查询设备信息,将信息结构化(设备ip名称,匹配了什么规则之类的)后发送…...
uniapp和VueI18n多语言H5项目语言国际化功能搭建流程
uniapp多语言项目国家化功能搭建流程 说明:uniapp多语言项目功能搭建分为应用部分和框架部分。 应用部分,即开发者自己的代码里涉及的界面部分的语言翻译。框架部分,即uni-app内置组件和API涉及界面的部分的语言翻译。 功能的搭建是需要un…...

C# | 凸包算法之Jarvis,寻找一组点的边界/轮廓
C#实现凸包算法之Jarvis 文章目录 C#实现凸包算法之Jarvis前言示例代码实现思路测试结果结束语 前言 这篇关于凸包算法的文章,本文使用C#和Jarvis算法来实现凸包算法。 首先消除两个最基本的问题: 什么是凸包呢? 凸包是一个包围一组点的凸多…...

SpringBoot接收请求参数的方式
【方式一】原始方式 因为SpringBoot封装了Servlet,所以也允许使用HttpServletRequest类中的方法来获取 /*** 【方式一】原始方式*/RequestMapping("/demo01")public String demo01(HttpServletRequest request) {// 参数名要与页面提交的参数名一致Strin…...

MKS SERVO4257D 闭环步进电机_系列5 CAN指令说明
第1部分 产品介绍 MKS SERVO 28D/35D/42D/57D 系列闭环步进电机是创客基地为满足市场需求而自主研发的一款产品。具备脉冲接口和RS485/CAN串行接口,支持MODBUS-RTU通讯协议,内置高效FOC矢量算法,采用高精度编码器,通过位置反馈&am…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...

12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...

基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

C# WPF 左右布局实现学习笔记(1)
开发流程视频: https://www.youtube.com/watch?vCkHyDYeImjY&ab_channelC%23DesignPro Git源码: GitHub - CSharpDesignPro/Page-Navigation-using-MVVM: WPF - Page Navigation using MVVM 1. 新建工程 新建WPF应用(.NET Framework) 2.…...

夏普比率(Sharpe ratio)
具有投资常识的人都明白,投资光看收益是不够的,还要看承受的风险,也就是收益风险比。 夏普比率描述的正是这个概念,即每承受一单位的总风险,会产生多少超额的报酬。 用数学公式描述就是: 其中࿱…...
Spring Boot + Thymeleaf 防重复提交
在 Spring Boot 与 Thymeleaf 结合的 Web 应用中,防止重复提交可以采用token 机制 客户端禁用按钮的方式实现,在高并发场景下,考虑使用 Redis 存储 token 而非 Session。 第一步:后端实现 Controller public class FormControl…...