后端代码

from flask import Flask, render_template, request, jsonify
from flask_wtf.csrf import CSRFProtect
from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) # 使用防csrf保护APP
csrf = CSRFProtect(app) class Config(object):
# sqlalchemy的配置参数
SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:123456@192.168.3.58:3306/test" # 设置sqlalchemy自动更跟踪数据库
SQLALCHEMY_TRACK_MODIFICATIONS = True SECRET_KEY = "doiso7fd89fyd9^(fsd" app.config.from_object(Config)
db = SQLAlchemy(app) # 定义作者模型类
class Author(db.Model):
__tablename__ = "tbl_author" id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50)) # 定义书籍模型类
class Book(db.Model):
__tablename__ = "tbl_book" id = db.Column(db.Integer, primary_key=True)
book_name = db.Column(db.String(50))
author_id = db.Column(db.Integer) @app.route("/")
def index():
book_num = db.session.query(Book).all()
if not book_num:
return render_template("book.html", books=[], page_list=[])
page_num = len(book_num)//10
if len(book_num) % 10 > 0:
page_num += 1
page_list = range(1, page_num + 1)
page = request.args.get("page")
if not page:
page = 1
else:
page = int(page) # 查询数据
ret_list = db.session.query(Book.id, Book.book_name, Author.name)\
.outerjoin(Author, Book.author_id == Author.id).order_by(Book.id)\
.slice((page-1)*10, page*10)\
.all()
return render_template("book.html", books=ret_list, page_list=page_list) @csrf.exempt # 取消csrf保护
@app.route("/del", methods=["POST"])
def delete():
"""删除书籍"""
# 提取参数
# 如果前端发送的请求体数据是json格式,get_json会解析成字典
# get_json 要求前端传送的数据的Content-Type: application/json
req_dict = request.get_json()
book_id = int(req_dict.get("book_id"))
if book_id == '':
resp_data = {"code": 1, "msg": "传入的id为空", "data": {}}
return jsonify(resp_data) books_id = db.session.query(Book.id).all() if (book_id,) not in books_id:
resp_data = {"code": 1, "msg": "删除的书籍不存在", "data": {}}
return jsonify(resp_data) # 删除数据
book = db.session.query(Book).get(book_id)
db.session.delete(book)
db.session.commit() # 构造响应数据
resp_data = {"code": 0, "msg": "删除成功", "data": {}}
return jsonify(resp_data) @app.route("/add", methods=["POST"])
def add():
"""增加书籍"""
# 获取请求信息
req_dict = request.get_json()
book_name = req_dict.get("name")
author_name = req_dict.get("author")
# 检查请求信息是否为空
if not all([book_name, author_name]):
# 为空则提示
resp_data = {"code": 1, "msg": "输入的数据不能为!", "data": {}}
return jsonify(resp_data) # 检查作者名称是否存在
authors_name = db.session.query(Author.name).all()
new_author = None
new_id = None
if (author_name,) not in authors_name:
# 不存在就创建
new_id = db.session.query(Author.id).order_by(-Author.id).first()[0] + 1
new_author = Author(id=new_id, name=author_name)
# 将新增数据加入会话中,等待最后一起提交
db.session.add(new_author) # 获取作者的id
if new_author:
author_id = new_id
else:
author_id = db.session.query(Author.id).filter(Author.name == author_name).one()[0] # 检查请求的书名
books_name = db.session.query(Book.book_name).filter(Book.author_id == author_id).all()
if (book_name,) in books_name:
# 存在则提示
resp_data = {"code": 1, "msg": "书籍已存在", "data": {}}
return jsonify(resp_data) new_book = Book(book_name=book_name, author_id=author_id)
db.session.add(new_book) # 留个长度超长BUG,验证该异常
try:
db.session.commit()
resp_data = {"code": 0, "msg": "创建成功", "data": {}}
return resp_data
except Exception as e:
db.session.rollback()
resp_data = {"code": 1, "msg": F"提交失败:{e}", "data": {}}
return resp_data if __name__ == '__main__':
# 删除所有表格(慎用)
# db.drop_all()
# db.create_all() app.run()

模板代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- 如果开启csrf保护,需要定义如下代码 -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>book_info</title>
<script src="/static/js/jquery-1.12.4.min.js"></script>
<script>
$(function(){
var book_name = $("#book_name")
var book_author = $("#book_author")
var csrftoken = $('meta[name=csrf-token]').attr('content')
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken)
}
}
}); // 获取URL后参数的值,name为参数名
$.getUrlParam = function (name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]); return null;
}
var current_page = $.getUrlParam("page") // 定义ajax请求函数
var req_post = function(url, data){
// 将js中的对象转换为 json字符串
var req_json = JSON.stringify(data);
$.ajax({
url: url,
type: "post",
// 申明传给后端的字符类型
contentType: "application/json",
dataType: 'json',
data: req_json
}).done(function(resp){
if (resp.code == 0)
{
if ( current_page != null){
if (url == "/del" && $(".del").length == 1 && current_page > 1){
current_page = current_page - 1
location.href = "/?page=" + current_page
}else{
location.href = "/?page=" + current_page
}
}else{
location.href = "/"
}
}
alert(resp.msg)
}).fail(function(){
console.log("请求失败")
});
}; // 创建书籍
$("#book_create").click(function(){
b_name = book_name.val();
b_author = book_author.val();
var data = {'name': b_name, 'author': b_author};
req_post("/add", data)
}); // 删除书籍
$(".del").click(function(){
var id = $(this).siblings()[0].innerHTML;
var data = {'book_id': id}
console.log("删除id为:" + id)
req_post("/del",data)
}); // 分页
$(".page div").click(function(){
var page_num = $(this)[0].innerHTML;
var data = "page=" + page_num
location.href = "/?" + data
});
})
</script>
<style>
* {
font-size: 16px;
}
#add {
margin-top: 50px;
margin-left: 100px;
float: left;
} #add div {
width: 400px;
margin: 10px auto 0px;
} #book_name, #book_author {
width: 200px;
border: 1px solid #000;
} #book_create {
width: 100px;
margin: auto;
} #book {
width: 500px;
background-color: rgba(113, 255, 161, 0.952);
margin-left: 50px;
float: left;
}; .th, .tr {
width: 500px;
height: 20px;
} .th div, .tr div{
width: 200px;
height: 30px;
float: left;
text-align: center;
line-height: 30px;
} .clearfix:before,.clearfix:after{
content:"";
display:table;
}
.clearfix:after{
clear:both;
}
.clearfix{
zoom:1;
} div.del{
width: 100px;
color: rgb(49, 0, 185);
} div.th3 {
width: 100px;
} .del:hover, .page div:hover{
cursor: pointer;
} .page {
width: 280px;
height: 20px;
margin: 20px;
} .page div {
width: 20px;
height: 20px;
float: left;
margin: 0px 5px;
text-align: center;
line-height: 20px;
} </style>
</head>
<body>
<div id="app">
<div id="add">
<div>书籍名称:<input type="text" id="book_name"></div>
<div>书籍作者:<input type="text" id="book_author"></div>
<div><input type="submit" id="book_create" value="新增"></div>
</div>
<div id="book">
<div class="th clearfix">
<div>书籍名称</div>
<div>作者</div>
<div class="th3">操作</div>
</div>
{% for book in books %}
<div class="tr clearfix">
<div style="display: none;">{{ book[0] }}</div>
<div>{{ book[1] }}</div>
<div>{{ book[2] }}</div>
<div class="del" >删除</div>
</div>
{% endfor %}
<div class="page">
{% for page in page_list %}
<div>{{ page }}</div> {% endfor %}
</div>
</div>
</div>
</body>
</html>

界面效果

 

最新文章

  1. ARCGIS SDE空间化处理
  2. 同感,C#对JSON序列化和反序列化有点蹩脚
  3. xml配置文件的读写
  4. S3C2440的Linux启动过程分析(一)——SC2440处理器结构
  5. 第7章 jQuery插件的使用和写法
  6. Shiro 整合SpringMVC 并且实现权限管理
  7. paip.简化字-手写参考二简字..共98个
  8. 【ASP.NET】C# 将HTML中Table导出到Excel(TableToExcel)
  9. NGUI3.5系列教程之 UILabel
  10. Cocos2dx-截屏并设置图片尺寸
  11. nginx配置ssl
  12. Android 开发之旅:深入分析布局文件&amp;又是“Hello World!”
  13. javaWeb Cache技术――OSCache(转-全)
  14. Android利用反射获取状态栏(StatusBar)高度
  15. 编辑简单的 shell程序
  16. macOS实现视频转音频以及音频拼接
  17. 【问题集】VS新建项目——失败——弹出“未将对象引用设置到对象的实例”
  18. DTCping 的简单使用与排错
  19. idea展现目录清晰方式
  20. ajax动态给select赋值

热门文章

  1. Java-如何合理的设置线程池大小
  2. 【MySQL】排名函数
  3. Declarative Pipeline 基础语法
  4. 【.NET 与树莓派】WS28XX 灯带的颜色渐变动画
  5. pf4j及pf4j-spring
  6. re正则表达式:import re ;re.search()
  7. ubantu电脑无法开机修复
  8. Centos使用kafka自带zookeeper安装kafka
  9. c++之升序和降序排序
  10. ubuntu下AF_INET和AF_INET6的值