Flask + flask_sqlalchemy + jq 完成书籍展示、新增、删除功能
后端代码
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>
界面效果

Flask + flask_sqlalchemy + jq 完成书籍展示、新增、删除功能的更多相关文章
- js jq 手机号实现(344) 附带删除功能 jq 实现银行卡没四个数加一个空格 附带删除功能
js 手机号实现(344) 下面有将正则验证去掉“-” 或“空格” 下一篇博客有单独的删除功能方法 <!DOCTYPE html> <head> <meta char ...
- PHP基础班初学心得:用JQ实现表单的全选、反选、取消和删除功能
摘要: 本人刚参加PHP基础班培训,由于之前毫无基础,分享的心得可能不规范,方法也许也"旁门左道",不能保证质量,只作自己总结学习,也希望能帮助到同样是初学者的朋友们,共同进步. ...
- SQL Server大量数据秒级插入/新增/删除
原文:SQL Server大量数据秒级插入/新增/删除 1.快速保存,该方法有四个参数,第一个参数为数据库连接,第二个参数为需要保存的DataTable,该参数的TableName属性需要设置为数据库 ...
- Mybatis入门教程之新增、更新、删除功能_java - JAVA
文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 上一节说了Mybatis的框架搭建和简单查询,这次我们来说一说用Mybatis进行基本的增删改操作: 一. 插入一条数据 ...
- 实例:SSH结合Easyui实现Datagrid的批量删除功能
在我先前的基础上面添加批量删除功能.实现的效果如下 删除成功 通常情况下删除不应该真正删除,而是应该有一个标志flag,但flag=true表示状态可见,但flag=false表示状态不可见,为删除状 ...
- h5、jq 移动端评论点攒功能
h5.jq 移动端评论点攒功能 平时做的项目中大部分都会涉及到评论的功能,之前用angular写的项目,功能写起来很方便,但是对于一个单页来说,angular有点大材小用了,所有今天分享一个关于jq制 ...
- input file样式修改,图片预览删除功能
本篇对input file进行了修改,改成自己需要的样式,类似验证身份上传身份证图片的功能. 效果图如下: 这里主要展示上传预览图片功能,对于删除功能的html及css写的比较粗糙,对于想要精细表现这 ...
- sns社交系统ThinkSNS+ 更新至V0.8.2,新增圈子功能
sns社交系统"ThinkSNS+"于7月15日发布了V0.8.0,含开源版本web+H5,及Android APP和iOS APP客户端. V0.8.2版本将于7月29日(本周六 ...
- 安卓listView实现下拉刷新上拉加载滑动仿QQ的删除功能
大家对这些功能都是看的多了,然后对上拉刷新和下拉加载的原理都是非常清楚的,所以实现这功能其实也就是为了让大家能够从众多的同行们来进行比较学习而已,虽然即使是这样,但是面试的时候面试官还是会问你上拉和下 ...
随机推荐
- Java 使用slf4j记录日志
引入依赖 <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12< ...
- java客户端的elasticSearch索引库的相关操作
package com.hope.es;import org.elasticsearch.client.transport.TransportClient;import org.elasticsear ...
- mybtis入门
1.编写持久化对象 public class User { private String id;//用户编号 private String username;//用户名 private String ...
- Java中的变量,数据类型和运算符
变量,数据类型和运算符 1.变量是一个数据存储空间的表示,它是储存数据的基本单元. 如何理解这句话,下面用一个表格可以形象的表达: 变量与房间之间的对应关系 房间名称 变量名 房间类型 变量类型 入住 ...
- Mysql配置文件 扩展详细配置
目录 配置文件中有些特定参数 扩展配置 max_connections connect_timeout interactive_timeout|wait_timeout net_retry_count ...
- aha
欢迎使用 MWeb MWeb 是专业的 Markdown 写作.记笔记.静态博客生成软件,目前已支持 Mac,iPad 和 iPhone.MWeb 有以下特色: 软件本身: 使用原生的 macOS 技 ...
- [BUUCTF]REVERSE——相册
相册 附件 步骤: apk文件,习惯用apkide打开,看它反编译成了jar,就换jadx-gui打开,题目提示找邮箱,因此在导航栏里搜索mail 看到了sendMailByJavaMail(java ...
- 万字长文入门 Redis 命令、事务、锁、订阅、性能测试
作者:痴者工良 Redis 基本数据类型 Redis 中,常用的数据类型有以下几种: String:字符串类型,二进制安全字符串: Hash:哈希表: List 列表:链表结构,按照插入顺序排序的字符 ...
- CF424A Squats 题解
Content 给定一个长度为 \(n\) 的仅由 x 和 X 组成的字符串,求使得字符串中 x 和 X 的数量相等需要修改的次数,并输出修改后的字符串. 数据范围:\(2\leqslant n\le ...
- JAVA中CountDownLatch的简单示例
public static void main(String[] args) throws InterruptedException { CountDownLatch latch =new Count ...