目录
一、新建项目并初始化
?二、安装依赖?axios、elementUI
三、Vue代码
四、进行接口联调
五、后端接口优化
六、web页面功能测试
七、总结
八、展望
九、附录(截止发文时的代码)
先来看看效果,再步入正题
主页
?增加
查询
详情
修改
删除
?先打一下地基
环境搭建博文:
VUE 3.0项目环境搭建+VS code安装(图文教程)_软件测试李同学的博客-CSDN博客
Flask+mysql接口增删改查博文:Flask+mysql实现增删改查接口开发+测试(图文教程附源码)_软件测试李同学的博客-CSDN博客
注意:本篇文章接着上面的图书项目book增删改查实现
一、新建项目并初始化
vue 创建新项目 :vue create book
初始化 :vue init webpack book
中间要是提示要安装脚手架:npm i -g @vue/cli-init
,按照提示执行命令即可
?安装:npm i -g @vue/cli-init
?
?
新建项目成功后,目录结构如下:
?二、安装依赖?axios、elementUI
axios说白了就是调接口用的
安装axios npm? npm install axios --save 安装element-ui? npm install element-ui --save (yarn add element-ui)
elementUI说白了就是一个组件库,很流行,实战的时候肯定是CV多,有轮子就不用重复写轮子
elementUI的引入
在src下面的main.js下新增如下内容 import Element from 'element-ui' import "element-ui/lib/theme-chalk/index.css" Vue.use(Element)
axios的引入 在src下面的main.js下新增如下内容 import axios from 'axios' Vue.prototype.$axios=axios 组件中,我们就可以通过this.$axios.get()来发起我们的请求了哈
通过命令 npm run dev? 启动
三、Vue代码
以下代码也是轮子,轮子有了,先看看效果
向src->components->HelloWorld.vue文件中加入以下代码,然后保存
<!--
Element-ui框架实现对数据库的增删改查
这里利用Vue进行简单的增删改查操作,可以与后台进行结合,进行增删改查的过程,只需要将接口改一下名字。
其中element-ui组件库经常与vue进行结合使用
-->
<template>
<div class="back">
<h1>{{ msg }}</h1>
<el-button :span="8" type="primary" @click="adduser" class="add-btn" plain>
添加信息
</el-button>
<el-input :span="8" placeholder="请输入内容" v-model="bookname" class="add-btn"
clearable>
</el-input>
<el-button :span="8" slot="append" icon="el-icon-search" @click="check"
class="button">
</el-button>
<el-table :data="bookInfo" style="width: 100%">
<el-table-column prop="id" label="编号" width="180">
</el-table-column>
<el-table-column prop="name" label="书名" width="180">
</el-table-column>
<el-table-column prop="writer" label="作者" width="180">
</el-table-column>
<el-table-column prop="publish" label="出版社" width="180">
</el-table-column>
<el-table-column align="right">
<!-- <template> -->
<el-input placeholder="请输?书名搜索" v-model="bookname" clearable>
</el-input>
<el-button slot="append" icon="el-icon-search" @click="check" class="button">
</el-button>
<!-- </template> -->
<template slot-scope="scope">
<el-button size="mini" @click="edit(scope.row,scope.row.id)">
编辑
</el-button>
<el-button size="mini" type="danger" @click.native.prevent="deleteRow(scope.row.id)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!--增加框-->
<el-dialog title="增加书籍信息" :visible.sync="dialogVisible1" width="30%" :before-close="handleClose1">
<div>
<el-form ref="form" :model="editObj1" label-width="80px">
<el-form-item label="书名">
<el-input v-model="editObj1.name">
</el-input>
</el-form-item>
<el-form-item label="作者">
<el-input v-model="editObj1.writer">
</el-input>
</el-form-item>
<el-form-item label="出版社">
<el-input v-model="editObj1.publish">
</el-input>
</el-form-item>
</el-form>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible1 = false">
取消
</el-button>
<el-button type="primary" @click="confirm1">
确定
</el-button>
</span>
</el-dialog>
<!--编辑框 -->
<el-dialog title="编辑书籍信息" :visible.sync="dialogVisible" width="30%" :before-close="handleClose">
<div>
<el-form ref="form" :model="editObj" label-width="80px">
<el-input type="hidden" v-model="editObj.id">
</el-input>
<el-form-item label="书名">
<el-input v-model="editObj.name">
</el-input>
</el-form-item>
<el-form-item label="作者">
<el-input v-model="editObj.writer">
</el-input>
</el-form-item>
<el-form-item label="出版社">
<el-input v-model="editObj.publish">
</el-input>
</el-form-item>
</el-form>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">
取消
</el-button>
<el-button type="primary" @click="confirm">
确定
</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
msg: "欢迎访问图书管理系统",
dialogVisible: false,
dialogVisible1: false,
bookname: '',
bookInfo: [{
id: '',
name: '',
writer: '',
publish: ''
}],
editObj: {
id: '',
name: '',
writer: '',
publish: ''
},
editObj1: {
name: '',
writer: '',
publish: ''
},
userIndex: 0,
}
},
mounted() {
this.getnetwork();
},
methods: {
getnetwork() {
// console.log(this.bookinfo.id);
var that = this
this.$axios.post("http://localhost:8081/springboot/getuser")
.then(function(res) {
console.log(res.data)
that.bookInfo = res.data
// console.log(this.bookInfo)
}).
catch(function(err) {
console.log(err)
})
},
//确定查询按钮
check() {
// console.log(this.bookname)
var that = this
//网络请求获取数据axios
this.$axios.post("http://localhost:8081/springboot/checkbyname", {
name: this.bookname,
}).then(function(res) { //请求成功,方法回调
//回调方法不能用this
console.log(res.data)
console.log(res.data.data)
that.bookInfo = res.data.data
// console.log(this.data.id)
}).
catch(function(err) { //请求失败
console.log(err)
})
},
adduser() {
this.dialogVisible1 = true;
},
edit(item, id) {
this.userIndex = id;
console.log(id)
// console.log(item.id)
// console.log(item.id)
this.editObj = {
id: item.id,
name: item.name,
writer: item.writer,
publish: item.publish,
};
this.dialogVisible = true;
},
deleteRow(bookid) {
console.log(bookid)
if (confirm('确定要删除吗') == true) {
var that = this
//网络请求获取数据axios
this.$axios.post("http://localhost:8081/springboot/deletebyid", {
id: bookid
})
.then(res =>{ //请求成功,方法回调
//回调方法不能this
this.getnetwork()
// getnetwork();
console.log(res.data)
that.newsList = res.data
// console.log(this.newsList);
}).catch(function(err) { //请求失败
console.log("失败了" + err)
})
}
// window.location.href = 'http://127.0.0.1:8848/HelloVue/book.html'
},
// ×按钮
handleClose() {
this.dialogVisible = false;
},
handleClose1() {
this.dialogVisible1 = false;
},
confirm() { //确认修改
console.log(this.editObj.id)
console.log(this.editObj.name)
console.log(this.editObj.publish)
console.log(this.editObj.writer)
var that = this
//网络请求获取数据axios
this.$axios.post("http://localhost:8081/springboot/updateuser", {
id: this.editObj.id,
name: this.editObj.name,
publish: this.editObj.publish,
writer: this.editObj.writer
}).then(function(res) { //请求成功,方法回调
//回调?方不能this
that.getnetwork()
console.log(res.data)
that.newsList = res.data
}).catch(function(err) { //请求失败
console.log(err)
})
this.dialogVisible = false;
// Vue.set(this.tableData, this.userIndex, this.editObj);
},
// 确定增加按钮
confirm1() {
var that = this
//网络请求获取数据axios
this.$axios.post("http://localhost:8081/springboot/adduser", {
name: this.editObj1.name,
publish: this.editObj1.publish,
writer: this.editObj1.writer
})
.then(function(res) { //请求成功,方法回调
//回调方法不能用this
that.getnetwork()
console.log(res.data)
that.newsList = res.data
}).
catch(function(err) { //请求失败
console.log(err)
})
this.dialogVisible1 = false;
// Vue.set(this.tableData, this.userIndex, this.editObj);
}
},
}
</script>
<style>
.add-btn{ width:450px }
.input{ width: 220px; height: 70px; }
.button{}
#app{ width: 1024px; margin: 0 auto; }
#back{ height: 200px; }
</style>
运行看看效果
?页面画好了,下一步和后端接口联调
四、进行接口联调
继续联调,发现vue文件还有很多需要改的地方
理智分析一波
1、先是先将对应的模板<template>写好,包括输入框(查找操作),增加按钮(增加操作),删除按钮(删除操作),修改按钮(修改操作),表格(显示数据)
模板代码如下:
<template>
<div class="back">
<h1>{{ msg }}</h1>
<el-button :span="8" type="primary" @click="addbook" class="add-btn" plain>
添加图书
</el-button>
<el-input :span="8" placeholder="请输入编号搜索" v-model="id" class="add-btn"
clearable>
</el-input>
<el-button :span="8" slot="append" icon="el-icon-search" @click="check"
class="button">
</el-button>
<el-table :data="bookInfo" style="width: 100%">
<el-table-column prop="id" label="编号" width="180">
</el-table-column>
<el-table-column prop="title" label="书名" width="180">
<template slot='header'>
<span class ="star">*</span>
<span >书名</span>
</template>
</el-table-column>
<el-table-column prop="author" label="作者" width="180">
<template slot='header'>
<span class ="star">*</span>
<span >作者</span>
</template>
</el-table-column>
<!-- 表头提示在这里用 -->
<el-table-column prop="read_status" label="阅读状态" width="180" :render-header="renderHeader">
<!-- 这里红星星没生效还需要找原因 -->
<template slot='header'>
<span class ="star">*</span>
<span >阅读状态</span>
</template>
</el-table-column>
<el-table-column align="right">
<template slot-scope="scope">
<!-- plain改变按钮显示方式,element 称为朴素按钮-->
<el-button size="mini" type="info" @click="detail(scope.row,scope.row.id)" >
详情
</el-button>
<el-button size="mini" type="success" @click="edit(scope.row,scope.row.id)">
编辑
</el-button>
<el-button size="mini" type="danger" @click.native.prevent="deleteRow(scope.row.id)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 数据分页页面,还没做好-->
<div class="block" >
<!--换行用br标签-->
<br><br/>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage4"
:page-sizes="[20, 30, 50, 100]"
:page-size="100"
layout="total, sizes, prev, pager, next, jumper"
:total="400">
</el-pagination>
</div>
<!--增加对话框-->
<el-dialog title="增加图书信息" :visible.sync="addbook_dialogVisible" width="30%" :before-close="handleClose1">
<div>
<el-form ref="form" :model="editObj1" label-width="80px">
<el-form-item label="书名" required="true">
<el-input v-model="editObj1.title" placeholder="请输入书名">
</el-input>
</el-form-item>
<el-form-item label="作者" required="true">
<el-input v-model="editObj1.author" placeholder="请输入作者">
</el-input>
</el-form-item>
<!--鼠标在此标签区域显示提示-->
<el-form-item label="阅读状态" required="true" title="阅读状态只能输入0或者1;0代表未读,1代表已读">
<el-input v-model="editObj1.read_status" placeholder="请输入阅读状态">
</el-input>
</el-form-item>
</el-form>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="addbook_dialogVisible = false">取消</el-button>
<el-button type="primary" @click="confirm_add">确定</el-button>
</span>
</el-dialog>
<!--编辑对话框 -->
<el-dialog title="编辑图书信息" :visible.sync="edit_dialogVisible" width="30%" :before-close="handleClose">
<div>
<el-form ref="form" :model="editObj" label-width="80px">
<el-input type="hidden" v-model="editObj.id"></el-input>
<!--required显示红星表示必填项,placeholder为输入框注释 -->
<el-form-item label="书名" required="true" >
<el-input v-model="editObj.title" placeholder="请输入书名"></el-input>
</el-form-item>
<el-form-item label="作者" required="true" >
<el-input v-model="editObj.author" placeholder="请输入作者"></el-input>
</el-form-item>
<el-form-item label="阅读状态" required="true" title="阅读状态只能输入0或者1;0代表未读,1代表已读">
<el-input v-model="editObj.read_status" placeholder="请输入阅读状态"></el-input>
</el-form-item>
</el-form>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="edit_dialogVisible = false">取消</el-button>
<el-button type="primary" @click="confirm">确定</el-button>
</span>
</el-dialog>
<!--详情对话框,新建一个对话框把编辑的代码复制过来,然后逻辑复制编辑额逻辑,再把确定和取消按钮去掉即可 -->
<el-dialog title="图书详情信息" :visible.sync="detail_dialogVisible" width="30%" :before-close="detail_handleClose">
<div>
<el-form ref="form" :model="editObj" label-width="80px">
<el-input type="hidden" v-model="editObj.id"></el-input>
<el-form-item label="书名" required="true">
<el-input v-model="editObj.title" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="作者" required="true">
<el-input v-model="editObj.author" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="阅读状态" required="true" title="阅读状态只能输入0或者1;0代表未读,1代表已读">
<el-input v-model="editObj.read_status" :disabled="true"></el-input>
</el-form-item>
</el-form>
</div>
<!--详情对话框的确定和取消按钮去掉
<span slot="footer" class="dialog-footer">
<el-button @click="edit_dialogVisible = false">取消</el-button>
<el-button type="primary" @click="confirm">确定</el-button>
</span>
-->
</el-dialog>
</div>
</template>
2、制作好模板之后,就得编写下各个方法,包括显示数据方法(getnetwork)增加方法(confirm_add),删除方法(deleteRow),查询方法(check),修改方法(confirm)
显示方法代码如下:
getnetwork() {
// console.log(this.bookinfo.id);
var that = this
this.$axios.post("http://127.0.0.1:5001/query",{
id: "", //这里不传id查所有
})
.then(function(res) {
console.log(res.data)
that.bookInfo = res.data.data
that.bookInfo = that.bookInfo.map(item=>{
item.read_status = String(item.read_status)
return item
}
)
// console.log(this.bookInfo)
}).
catch(function(err) {
console.log(err)
})
}
增加方法(confirm_add)如下:
//5、 增加方法
confirm_add() {// 确定增加按钮
if (this.editObj1.title === '') {
this.$message({
message: '书名不能为空!',
type: 'warning'
});
return
}
if (this.editObj1.author === '') {
this.$message({
message: '作者不能为空!',
type: 'warning'
});
return
}
if (this.editObj1.read_status === '') {
this.$message({
message: '阅读状态不能为空!',
type: 'warning'
});
return
}
var that = this
//网络请求获取数据axios
this.$axios.post("http://127.0.0.1:5001/add", {
title: this.editObj1.title,
author: this.editObj1.author,
read_status: this.editObj1.read_status
}).then(function(res) { //请求成功,方法回调
// this.$message.success('图书添加成功!');
//回调方法不能用this
that.getnetwork()
// if (this.editObj1.read_status == success)
console.log(res.data)
//that.newsList = res.data
}).catch(function(err) { //请求失败
console.log(err)
})
this.addbook_dialogVisible = false;
// Vue.set(this.tableData, this.userIndex, this.editObj);
},
// 给表头增加提示
renderHeader(h,{column}){
const serviceContent= [
h('div',{
slot:"content",
},
"提示:true代表已读,false代表未读"
)
]
return h("div",[
h("span",column.label),
h("el-tooltip",{
props:{
placement:"top"
}
},
[
serviceContent,
h("i",{
class:"el-icon-warning-outline",
style:"color:blue;margin-left:5px;"
})
])
]);
},
},
}
删除方法(deleteRow)如下:
//3、删除方法
deleteRow(id) {
console.log(id)
if (confirm('确定要删除吗') == true) {
var that = this
//网络请求获取数据axios
this.$axios.post("http://127.0.0.1:5001/delete", {
id:id
})
.then(res =>{ //请求成功,方法回调
//回调方法不能this
this.getnetwork()
// getnetwork();
console.log(res.data)
}).catch(function(err) { //请求失败
console.log("失败了" + err)
})
}
},
// 对话框右上角的×按钮
handleClose() {//编辑
this.edit_dialogVisible = false;
},
handleClose1() {//增加
this.addbook_dialogVisible = false;
},
detail_handleClose() {//详情
this.detail_dialogVisible = false;
}
查询方法(check)如下:
//2、查询方法
check() {//确定查询按钮
// console.log(this.bookname)
var that = this
//网络请求获取数据axios
this.$axios.post("http://127.0.0.1:5001/query", {
id: this.id,
}).then(function(res) { //请求成功,方法回调
//回调方法不能用this
console.log(res.data)
console.log(res.data.data)
that.bookInfo = res.data.data
that.bookInfo = that.bookInfo.map(item=>{//布尔类型转字符串
item.read_status = String(item.read_status)
return item
})
// console.log(this.data.id)
}).
catch(function(err) { //请求失败
console.log(err)
})
},
修改方法(confirm)?如下:
//4、修改方法
confirm() { //确认修改
if (this.editObj.title === '') {
this.$message({
message: '书名不能为空!',
type: 'warning'
});
return
}
if (this.editObj.author === '') {
this.$message({
message: '作者不能为空!',
type: 'warning'
});
return
}
if (this.editObj.read_status === '') {
this.$message({
message: '阅读状态不能为空!',
type: 'warning'
});
return
}
var that = this
//网络请求获取数据axios
this.$axios.post("http://127.0.0.1:5001/update", {
id: this.editObj.id,
title: this.editObj.title,
author: this.editObj.author,
read_status: this.editObj.read_status
}).then(function(res) { //请求成功,方法回调
//回调方法不能this
that.getnetwork()
console.log(res.data)
}).catch(function(err) { //请求失败
console.log(err)
})
this.edit_dialogVisible = false;
// Vue.set(this.tableData, this.userIndex, this.editObj);
},
五、后端接口优化
1、传单个id的时候返回的单个数据没在数组里,这里要处理一下
2、删除的方法由DELETE改为POST
3、。。。。还有很多别的,具体看代码
六、web页面功能测试
准备测试,看看增删改查效果
增加
删除
?
修改
查询
查询所有
通过编号查询?
其他的测试场景和细节体验这里就不测试了
代码的注释已经写得很清楚了?
七、总结
上一篇博文的代码有一些bug,不知道大家找出来没。这一次做的增删改查前端加入了很多小细节,基本是就是工作中需要测试的细节,如果是自己实现的话,这个会给大家带来很深的印象。
还有对阅读状态这个布尔型字段的处理,有点费功夫的,坑也多
八、期望
很多校验还没做好,还有很多bug,前期设计不太合理,后续需要优化。
1、更改为书名查询,模糊查询
2、修复增加和修改后页面自动按照id查询的bug。。。等bug
3、增加输入框长度校验、提示校验,目前做的还不够
4、增加操作成功和失败后的提示
5、删除确认框的处理
6、做好分页功能
7、做好封装,接口、方法等
8、。。。。。。
完成以上工作,一个健壮的增删改查就有了,已经满足工作的要求了
九、附录(截止发文时的代码)
1、后端app.py全部代码
# -*- coding: utf-8 -*-
# @Author : Liqiju
# @Time : 2022/5/1 2:45
# @File : app.py
# @Software: PyCharm
import pymysql
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask import make_response,request
from flask_cors import CORS
pymysql.install_as_MySQLdb()
app = Flask(__name__)
# ------------------database----------------------------
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:root@localhost:3306/books'
# 指定数据库文件
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
# 允许修改跟踪数据库
db = SQLAlchemy(app)
class Books(db.Model):
id = db.Column(db.Integer, primary_key=True, comment='自动递增id,唯一键')
title = db.Column(db.String(80), nullable=False, comment='书名')
author = db.Column(db.String(120), nullable=False, comment='作者')
read_status = db.Column(db.Boolean, comment='阅读状态,0未读,1已读') # bool的True和False是数值1和0
# 增加数据
def insert_data(title, author, read_status):
book = Books(title=title, author=author, read_status=read_status)
db.session.add_all([book])
db.session.commit()
# 查询所有
def select_data_all():
book_list = []
books = Books.query.all()
# 类似于 select * from Books
for s in books:
dic = {}
dic['id'] = s.id
dic['title'] = s.title
dic['author'] = s.author
dic['read_status'] = s.read_status
book_list.append(dic)
return book_list
# 通过id查询
def select_data_by_id(id):
book_list = []
book = Books.query.get(id)
if not book:
return False
dic = {}
dic['id'] = book.id
dic['title'] = book.title
dic['author'] = book.author
dic['read_status'] = book.read_status
book_list.append(dic)
return book_list
# 通过id删除数据
def delete_data(id):
# 类似于 select * from Books where id = id
delete_id = Books.query.get(id)
if not delete_id:
return False
db.session.delete(delete_id)
db.session.commit()
# 提交操作到数据库
# 修改数据
def update_data(id, title='', author='', read_status=''):
book = Books.query.get(id)
if not title == '':
book.title = title
if not author == '':
book.author = author
if not read_status == '':
book.read_status = read_status
db.session.commit()
# 解决浏览器浏览器访问输出乱码问题
app.config['JSON_AS_ASCII'] = False
@app.after_request
def after(resp):
resp = make_response(resp)
resp.headers['Access-Control-Allow-Origin'] = '*' # 允许跨域地址
resp.headers['Access-Control-Allow-Methods'] = '*' # 请求 ‘*’ 就是全部
resp.headers['Access-Control-Allow-Headers'] = 'x-requested-with,content-type' # 头部
resp.headers['Access-Control-Allow-Credentials'] = 'True'
return resp
CORS(app, resources=r'/*', supports_credentials=True)
# 前端通过传参title、author、read_status增加书籍
@app.route('/add', methods=['POST'])
def add():
response_object = {'status': 'success'}
if request.method == 'POST':
post_data = request.get_json()
print('调用add方传过来的参数是', post_data)
book_list = select_data_all()
for i in range(len(book_list)):
title_list = book_list[i]['title']
if post_data.get('title') in title_list:
response_object['message'] = '书名(title)重复!'
response_object["status"]= 'fail'
return response_object
if post_data.get('title') is None:
response_object['message'] = 'title是必传参数!'
response_object["status"]= 'fail'
return response_object
if post_data.get('author') is None:
response_object['message'] = 'author是必传参数!'
response_object["status"]= 'fail'
return response_object
if post_data.get('read_status') is None:
response_object['message'] = 'read_status是必传参数!'
response_object["status"]= 'fail'
return response_object
title = str(post_data.get('title')).strip(),
author = str(post_data.get('author')).strip(),
read_status = int(str(post_data.get('read_status')))# 前端传过来字符串处理为int
if title[0] is None or title[0] is '':
response_object['message'] = 'title不能为空!'
response_object["status"] = 'fail'
return response_object
if author[0] is None or author[0] is '':
response_object['message'] = '作者不能为空!'
response_object["status"] = 'fail'
return response_object
if read_status != 0 and read_status != 1:
response_object['message'] = '阅读状态只能为0和1!'
response_object["status"] = 'fail'
return response_object
insert_data(title=title[0], author=author[0], read_status=read_status)
response_object['message'] = '图书添加成功!'
return response_object
# 前端通过传id删除书籍
@app.route('/delete', methods=['POST']) # 改为post方法
def delete():
response_object = {'status': 'success'}
if request.method == 'POST':
post_data = request.get_json()
print('调用delete方传过来的参数是:', post_data)
if post_data.get('id') is None:
response_object['message'] = 'id是必传参数!'
response_object["status"]= 'fail'
return response_object
id = post_data.get('id')
result = delete_data(id) # 删除方法调用
if result is False:
response_object['message'] = '需要删除的图书不存在!'
response_object["status"] = 'fail'
return response_object
else:
response_object['message'] = '图书被删除!'
return response_object
# 前端通过传参title、author、read_status修改书籍
@app.route('/update', methods=['POST'])
def update():
response_object = {'status': 'success'}
if request.method == 'POST':
post_data = request.get_json()
print('调用update方传过来的参数是', post_data)
if post_data.get('id') is None:
response_object['message'] = 'id是必传参数!'
response_object["status"]= 'fail'
return response_object
if post_data.get('title') is None:
response_object['message'] = 'title是必传参数!'
response_object["status"]= 'fail'
return response_object
if post_data.get('author') is None:
response_object['message'] = 'author是必传参数!'
response_object["status"]= 'fail'
return response_object
if post_data.get('read_status') is None:
response_object['message'] = 'read_status是必传参数!'
response_object["status"]= 'fail'
return response_object
# 查询所有数据
book_list = select_data_all()
# 拼接所有的id到列表
print(book_list)
# 这里的逻辑写错了,有bug,改一下
book_id = []
for i in range(len(book_list)):
book_id.append(book_list[i]['id'])
print('book_id是', book_id)
# 判断书籍id在不在列表内
if post_data.get('id') not in book_id and int(post_data.get('id')) not in book_id: # 这里也有bug,改一下
response_object['message'] = '需要修改的图书id不存在!'
response_object["status"]= 'fail'
return response_object
title = str(post_data.get('title')).strip(),
author = str(post_data.get('author')).strip(),
#print("处理前",post_data.get('read_status'))
read_status = int(post_data.get('read_status')) # 前端传过来字符串处理为int
#print("处理后", read_status)
if title[0] is None or title[0] is '':
response_object['message'] = 'title不能为空!'
response_object["status"] = 'fail'
return response_object
if author[0] is None or author[0] is '':
response_object['message'] = '作者不能为空!'
response_object["status"] = 'fail'
return response_object
if read_status != 0 and read_status != 1:
response_object['message'] = '阅读状态只能为0和1!'
response_object["status"] = 'fail'
return response_object
books_id = post_data.get('id')
title = post_data.get('title')
author = post_data.get('author')
read_status = read_status
# 这里原来的post_data.get('read_status')改为read_status,上面已经处理了
update_data(id=books_id, title=title, author=author, read_status=read_status)
response_object['message'] = '图书已更新!'
return response_object
# 前端通过不传参默认查询所有书籍,传id查询对应书籍
@app.route('/query', methods=['POST'])
def query():
response_object = {'status': 'success'}
if request.method == 'POST':
post_data = request.get_json()
print('调用query方传过来的参数是', post_data)
# if post_data.get('id') is None:
id = str(post_data.get('id')).strip()
if id is None or id is '':
books = select_data_all()
response_object['message'] = '查询所有图书成功!'
response_object['data'] = books
return response_object
# id = str(post_data.get('id')).strip()
# if id is None or id is '':
# response_object['message'] = 'id不能为空!'
# response_object["status"] = 'fail'
# return response_object
book = select_data_by_id(id)
if book is False:
response_object['message'] = '需要查询的图书不存在!'
response_object["status"] = 'fail'
return response_object
else:
response_object['message'] = '图书查询成功!'
response_object['data'] = book
return response_object
if __name__ == '__main__':
# 默认是5000,这里设置5001避免本地冲突。打开debug方便调试
# db.create_all() # 创建表(表创建好后可注释掉)
# insert_data("《水浒传》", "吴承恩", 1) # 利用这个可以添加数据或者直接数据库手动加入
# 注意这个时候没开启校验title唯一性是因为不是前端过来的请求
app.run(debug=True, port=5001)
2、前端HelloWorld.vue全部代码
<!--
Element-ui框架实现对数据库的增删改查
这里利用Vue进行简单的增删改查操作,可以与后台进行结合,进行增删改查的过程,只需要将接口改一下名字。
其中element-ui组件库经常与vue进行结合使用
vue被称为组件,那是因为一个vue文件由HTML、JS、CSS构成
-->
<!--一、 HTML部分,用的是element-ui 模板template -->
<template>
<div class="back">
<h1>{{ msg }}</h1>
<el-button :span="8" type="primary" @click="addbook" class="add-btn" plain>
添加图书
</el-button>
<el-input :span="8" placeholder="请输入编号搜索" v-model="id" class="add-btn"
clearable>
</el-input>
<el-button :span="8" slot="append" icon="el-icon-search" @click="check"
class="button">
</el-button>
<el-table :data="bookInfo" style="width: 100%">
<el-table-column prop="id" label="编号" width="180">
</el-table-column>
<el-table-column prop="title" label="书名" width="180">
<template slot='header'>
<span class ="star">*</span>
<span >书名</span>
</template>
</el-table-column>
<el-table-column prop="author" label="作者" width="180">
<template slot='header'>
<span class ="star">*</span>
<span >作者</span>
</template>
</el-table-column>
<!-- 表头提示在这里用 -->
<el-table-column prop="read_status" label="阅读状态" width="180" :render-header="renderHeader">
<!-- 这里红星星没生效还需要找原因 -->
<template slot='header'>
<span class ="star">*</span>
<span >阅读状态</span>
</template>
</el-table-column>
<el-table-column align="right">
<template slot-scope="scope">
<!-- plain改变按钮显示方式,element 称为朴素按钮-->
<el-button size="mini" type="info" @click="detail(scope.row,scope.row.id)" >
详情
</el-button>
<el-button size="mini" type="success" @click="edit(scope.row,scope.row.id)">
编辑
</el-button>
<el-button size="mini" type="danger" @click.native.prevent="deleteRow(scope.row.id)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 数据分页页面,还没做好-->
<div class="block" >
<!--换行用br标签-->
<br><br/>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage4"
:page-sizes="[20, 30, 50, 100]"
:page-size="100"
layout="total, sizes, prev, pager, next, jumper"
:total="400">
</el-pagination>
</div>
<!--增加对话框-->
<el-dialog title="增加图书信息" :visible.sync="addbook_dialogVisible" width="30%" :before-close="handleClose1">
<div>
<el-form ref="form" :model="editObj1" label-width="80px">
<el-form-item label="书名" required="true">
<el-input v-model="editObj1.title" placeholder="请输入书名">
</el-input>
</el-form-item>
<el-form-item label="作者" required="true">
<el-input v-model="editObj1.author" placeholder="请输入作者">
</el-input>
</el-form-item>
<!--鼠标在此标签区域显示提示-->
<el-form-item label="阅读状态" required="true" title="阅读状态只能输入0或者1;0代表未读,1代表已读">
<el-input v-model="editObj1.read_status" placeholder="请输入阅读状态">
</el-input>
</el-form-item>
</el-form>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="addbook_dialogVisible = false">取消</el-button>
<el-button type="primary" @click="confirm_add">确定</el-button>
</span>
</el-dialog>
<!--编辑对话框 -->
<el-dialog title="编辑图书信息" :visible.sync="edit_dialogVisible" width="30%" :before-close="handleClose">
<div>
<el-form ref="form" :model="editObj" label-width="80px">
<el-input type="hidden" v-model="editObj.id"></el-input>
<!--required显示红星表示必填项,placeholder为输入框注释 -->
<el-form-item label="书名" required="true" >
<el-input v-model="editObj.title" placeholder="请输入书名"></el-input>
</el-form-item>
<el-form-item label="作者" required="true" >
<el-input v-model="editObj.author" placeholder="请输入作者"></el-input>
</el-form-item>
<el-form-item label="阅读状态" required="true" title="阅读状态只能输入0或者1;0代表未读,1代表已读">
<el-input v-model="editObj.read_status" placeholder="请输入阅读状态"></el-input>
</el-form-item>
</el-form>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="edit_dialogVisible = false">取消</el-button>
<el-button type="primary" @click="confirm">确定</el-button>
</span>
</el-dialog>
<!--详情对话框,新建一个对话框把编辑的代码复制过来,然后逻辑复制编辑额逻辑,再把确定和取消按钮去掉即可 -->
<el-dialog title="图书详情信息" :visible.sync="detail_dialogVisible" width="30%" :before-close="detail_handleClose">
<div>
<el-form ref="form" :model="editObj" label-width="80px">
<el-input type="hidden" v-model="editObj.id"></el-input>
<el-form-item label="书名" required="true">
<el-input v-model="editObj.title" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="作者" required="true">
<el-input v-model="editObj.author" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="阅读状态" required="true" title="阅读状态只能输入0或者1;0代表未读,1代表已读">
<el-input v-model="editObj.read_status" :disabled="true"></el-input>
</el-form-item>
</el-form>
</div>
<!--详情对话框的确定和取消按钮去掉
<span slot="footer" class="dialog-footer">
<el-button @click="edit_dialogVisible = false">取消</el-button>
<el-button type="primary" @click="confirm">确定</el-button>
</span>
-->
</el-dialog>
</div>
</template>
<!--二、下面是JS部分-->
<script>
export default {
data() {
return {
msg: "欢迎访问图书管理系统",
edit_dialogVisible: false,
addbook_dialogVisible: false,
detail_dialogVisible: false,
id: '',
title: '',
author: '',
read_status: '',
bookInfo: [{
id: '',
title: '',
author: '',
read_status: ''
}],
editObj: {
id: '',
title: '',
author: '',
read_status: ''
},
editObj1: {
title: '',
author: '',
read_status: ''
},
userIndex: 0,
}
},
mounted() {
this.check();
},
methods: {
//1、显示方法
getnetwork() {
// console.log(this.bookinfo.id);
var that = this
this.$axios.post("http://127.0.0.1:5001/query",{
id: "", //这里不传id查所有
})
.then(function(res) {
console.log(res.data)
that.bookInfo = res.data.data
that.bookInfo = that.bookInfo.map(item=>{
item.read_status = String(item.read_status)
return item
}
)
// console.log(this.bookInfo)
}).
catch(function(err) {
console.log(err)
})
},
//2、查询方法
check() {//确定查询按钮
// console.log(this.bookname)
var that = this
//网络请求获取数据axios
this.$axios.post("http://127.0.0.1:5001/query", {
id: this.id,
}).then(function(res) { //请求成功,方法回调
//回调方法不能用this
console.log(res.data)
console.log(res.data.data)
that.bookInfo = res.data.data
that.bookInfo = that.bookInfo.map(item=>{//布尔类型转字符串
item.read_status = String(item.read_status)
return item
})
// console.log(this.data.id)
}).
catch(function(err) { //请求失败
console.log(err)
})
},
addbook() {
this.addbook_dialogVisible = true;
},
edit(item, id) {
this.id = id;
console.log(id)
this.editObj = {
id: item.id,
title: item.title,
author: item.author,
read_status: item.read_status,
};
this.edit_dialogVisible = true;
},
detail(item, id) {
this.id = id;
console.log(id)
this.editObj = {
id: item.id,
title: item.title,
author: item.author,
read_status: item.read_status,
};
this.detail_dialogVisible = true;
},
//3、删除方法
deleteRow(id) {
console.log(id)
if (confirm('确定要删除吗') == true) {
var that = this
//网络请求获取数据axios
this.$axios.post("http://127.0.0.1:5001/delete", {
id:id
})
.then(res =>{ //请求成功,方法回调
//回调方法不能this
this.getnetwork()
// getnetwork();
console.log(res.data)
}).catch(function(err) { //请求失败
console.log("失败了" + err)
})
}
},
// 对话框右上角的×按钮
handleClose() {//编辑
this.edit_dialogVisible = false;
},
handleClose1() {//增加
this.addbook_dialogVisible = false;
},
detail_handleClose() {//详情
this.detail_dialogVisible = false;
},
//4、修改方法
confirm() { //确认修改
if (this.editObj.title === '') {
this.$message({
message: '书名不能为空!',
type: 'warning'
});
return
}
if (this.editObj.author === '') {
this.$message({
message: '作者不能为空!',
type: 'warning'
});
return
}
if (this.editObj.read_status === '') {
this.$message({
message: '阅读状态不能为空!',
type: 'warning'
});
return
}
var that = this
//网络请求获取数据axios
this.$axios.post("http://127.0.0.1:5001/update", {
id: this.editObj.id,
title: this.editObj.title,
author: this.editObj.author,
read_status: this.editObj.read_status
}).then(function(res) { //请求成功,方法回调
//回调方法不能this
that.getnetwork()
console.log(res.data)
}).catch(function(err) { //请求失败
console.log(err)
})
this.edit_dialogVisible = false;
// Vue.set(this.tableData, this.userIndex, this.editObj);
},
//5、 增加方法
confirm_add() {// 确定增加按钮
if (this.editObj1.title === '') {
this.$message({
message: '书名不能为空!',
type: 'warning'
});
return
}
if (this.editObj1.author === '') {
this.$message({
message: '作者不能为空!',
type: 'warning'
});
return
}
if (this.editObj1.read_status === '') {
this.$message({
message: '阅读状态不能为空!',
type: 'warning'
});
return
}
var that = this
//网络请求获取数据axios
this.$axios.post("http://127.0.0.1:5001/add", {
title: this.editObj1.title,
author: this.editObj1.author,
read_status: this.editObj1.read_status
}).then(function(res) { //请求成功,方法回调
// this.$message.success('图书添加成功!');
//回调方法不能用this
that.getnetwork()
// if (this.editObj1.read_status == success)
console.log(res.data)
//that.newsList = res.data
}).catch(function(err) { //请求失败
console.log(err)
})
this.addbook_dialogVisible = false;
// Vue.set(this.tableData, this.userIndex, this.editObj);
},
// 给表头增加提示
renderHeader(h,{column}){
const serviceContent= [
h('div',{
slot:"content",
},
"提示:true代表已读,false代表未读"
)
]
return h("div",[
h("span",column.label),
h("el-tooltip",{
props:{
placement:"top"
}
},
[
serviceContent,
h("i",{
class:"el-icon-warning-outline",
style:"color:blue;margin-left:5px;"
})
])
]);
},
},
}
</script>
<!-- 三、CSS部分 颜色、样式自己调试,这里就能体会有UI工程师的好处-->
<style>
/**标签为class属性就用.修饰,标签属性为id的话用#修饰。**/
.add-btn{ width:450px }
.input{ width: 220px; height: 70px; }
.button{
color: rgb(246, 241, 248);
background-color: rgb(187, 187, 221);
}
#app{ width: 1024px; margin: 0 auto; }
#back{ height: 200px; }
.block{text-align:left}
.star{
color: #F56C6C;
font-size: 14px;
margin-right: 4px;
}
</style>
有疑问来评论区或者私信一起学习交流
|