✨✨ 欢迎大家来到景天科技苑✨✨
?? 养成好习惯,先赞后看哦~??
? 作者简介:景天科技苑
?《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
?《博客》:Python全栈,前后端开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,linux,shell脚本等实操经验,网站搭建,面试宝典等分享。
所属的专栏:flask框架零基础,进阶应用实战教学
景天的主页:景天科技苑
文章目录
flask项目中数据库连接设置数据库基本操作模型类定义 flask中数据表操作创建和删除表数据操作添加一条数据添加多条数据更新操作删除操作 关于数据库锁总结上一章,我们学到了在python中怎么使用SQLAlchemy来操作数据库,在工作中,我们经常结合flask来操作数据库。本章我们来一起深入探讨下!!!
flask项目中数据库连接设置
在 Flask-SQLAlchemy 中,数据库的链接配置信息使用URL指定,而且程序使用的数据库必须保存到Flask的 SQLALCHEMY_DATABASE_URI 配置项中manage.py,代码:
# SQLAlchemy的链接配置:"数据库名://账户名:密码@服务器地址:端口/数据库名称?配置参数选项"app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:123@127.0.0.1:3306/flaskdemo?charset=utf8mb4"# 如果不使用mysqldb改用pymysql,则需要在连接时指定pymysql# app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:Jin*******7!@10.10.0.52:3306/students?charset=utf8mb4"
其他设置项:
# 动态追踪修改设置,如未设置只会提示警告app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True# 查询时会显示原始SQL语句app.config["SQLALCHEMY_ECHO"] = True
常用的SQLAlchemy字段类型与python数据类型对照
常用的SQLAlchemy列约束选项
数据库基本操作
在SQLAlchemy中,添加、修改、删除操作,均由数据库会话(sessionSM)管理。 会话用 db.session 表示。在准备把数据写入数据库前,要先将数据添加到会话中然后调用 db.session.commit() 方法提交会话。 在SQLAlchemy 中,查询操作是通过 query 对象操作数据。 最基本的查询是返回表中所有数据,也可以通过filter或filter_by过滤器进行更精确的数据库查询。模型类定义
我们后面会把模型创建到单独的文件中,但是现在我们先把模型类写在main.py文件中。
from flask import Flaskfrom flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)# 连接数据库连接urlapp.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:Jinghao31357!@10.10.0.52:3306/students?charset=utf8mb4"# 动态追踪修改设置,如未设置只会提示警告app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True# 查询时会显示原始SQL语句app.config["SQLALCHEMY_ECHO"] = True# 把SQLAlchemy组件注册到项目中db = SQLAlchemy()db.init_app(app)#创建模型类class Student(db.Model): """学生信息模型""" #下面的字段配置相当于执行sql语句如下 """ CREATE TABLE tb_student2 ( id INTEGER NOT NULL COMMENT '主键' AUTO_INCREMENT, name VARCHAR(15) COMMENT '姓名', age SMALLINT COMMENT '年龄', sex BOOL COMMENT '性别', email VARCHAR(128) COMMENT '邮箱地址', money NUMERIC(10, 2) COMMENT '钱包', PRIMARY KEY (id), UNIQUE (email) ) """ # 声明与当前模型绑定的数据表名称 __tablename__ = "tb_student2" id = db.Column(db.Integer, primary_key=True, comment="主键") name = db.Column(db.String(15), index=True, comment="姓名") age = db.Column(db.SmallInteger, comment="年龄") sex = db.Column(db.Boolean, default=True, comment="性别") email = db.Column(db.String(128), unique=True, comment="邮箱地址") money = db.Column(db.Numeric(10, 2), default=0.0, comment="钱包") def __repr__(self): # 相当于django的__str__ return f"{self.name}<{self.__class__.__name__}>"class Course(db.Model): """课程模型""" """ CREATE TABLE tb_course ( id INTEGER NOT NULL COMMENT '主键' AUTO_INCREMENT, name VARCHAR(255) COMMENT '课程', price NUMERIC(8, 2) COMMENT '价格', PRIMARY KEY (id), UNIQUE (name) ) """ __tablename__ = "tb_course" id = db.Column(db.Integer, primary_key=True, comment="主键") name = db.Column(db.String(255), unique=True, comment="课程") price = db.Column(db.Numeric(8, 2), comment="价格") def __repr__(self): # 相当于django的__str__ return f"{self.name}<{self.__class__.__name__}>"class Teacher(db.Model): """老师模型""" """ CREATE TABLE tb_teacher ( id INTEGER NOT NULL COMMENT '主键' AUTO_INCREMENT, name VARCHAR(255) COMMENT '姓名', `option` ENUM('讲师','助教','班主任'), PRIMARY KEY (id), UNIQUE (name) ) """ __tablename__ = "tb_teacher" id = db.Column(db.Integer, primary_key=True, comment="主键") name = db.Column(db.String(255), unique=True, comment="姓名") option = db.Column(db.Enum("讲师", "助教", "班主任"), default="讲师") def __repr__(self): return f"{self.name}<{self.__class__.__name__}>"if __name__ == '__main__': #要想执行创建表,需要调用db.creat_all(),db要想被调用,需要放到app上下文里面 with app.app_context(): # 如果没有提前声明模型中的数据表,则可以采用以下代码生成数据表, # 如果数据库中已经声明了有数据表,则不会继续生成 db.create_all() app.run(debug=True)
flask中数据表操作
创建和删除表
创建表
# 在视图内调用:@app.route("/create")def create_table(): db.create_all() # 为项目中被识别的所有模型创建数据表 return "ok"# 在视图以外的地方调用:with app.app_context(): # create_all()方法执行的时候,需要放在模型的后面 # 检测数据库中是否存在和模型匹配的数据表。 # 如果没有,则根据模型转换的建表语句进行建表。 # 如果找到,则不会进行额外处理 db.create_all()
删除表
# 在视图内调用:@app.route("/drop")def drop_table(): db.drop_all() # 为项目中被识别的所有模型删除数据表 return "ok"# 在视图以外的地方调用: with app.app_context(): db.drop_all() # 慎用,很给力的!!这表示删除数据库中所有模型对应的表。
数据操作
添加一条数据
#在视图函数中实现增删改查@app.route("/data")def data(): """添加数据""" # # 添加一条数据 student = Student( name="小明", age=17, sex=True, email="xiaoming@qq.com", money=30.50 ) db.session.add(student) db.session.commit() return "ok"
get请求访问data路径
可以看到数据已被添加到表中
添加多条数据
student_list = [ Student(name="小黑", age=16, sex=True, email="xiaohei@qq.com", money=1000), Student(name="小红", age=15, sex=False, email="xiaohong@qq.com", money=1200), Student(name="小兰", age=11, sex=True, email="xiaolan@qq.com", money=600), Student(name="小白", age=21, sex=False, email="xiaobai@qq.com", money=2900),]db.session.add_all(student_list)db.session.commit()
查看数据库
更新操作
更新一条数据
student = Student.query.get(3)student.age = 18db.session.commit()
更新之前,我们先看下3号的年龄
浏览器访问后查看
可见年龄被修改成18
更新多条数据
Student.query.filter(Student.sex == True).update({ Student.money: Student.age * 100,})db.session.commit()
可见sex为True的money改成了年龄乘以100
删除操作
删除一条数据
student = Student.query.get(5)db.session.delete(student)db.session.commit()
id为5的数据被删除
删除多条数据
Student.query.filter(Student.sex==False).delete()db.session.commit()
删之前先看看数据库表数据
浏览器访问/data
查看数据库,sex为False的全部被删除
完整代码:
from flask import Flaskfrom flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)# 连接数据库连接urlapp.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:Jinghao31357!@10.10.0.52:3306/students?charset=utf8mb4"# 动态追踪修改设置,如未设置只会提示警告app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True# 查询时会显示原始SQL语句app.config["SQLALCHEMY_ECHO"] = True# 把SQLAlchemy组件注册到项目中db = SQLAlchemy()db.init_app(app)#创建模型类class Student(db.Model): """学生信息模型""" # 声明与当前模型绑定的数据表名称 __tablename__ = "tb_student2" id = db.Column(db.Integer, primary_key=True, comment="主键") name = db.Column(db.String(15), index=True, comment="姓名") age = db.Column(db.SmallInteger, comment="年龄") sex = db.Column(db.Boolean, default=True, comment="性别") email = db.Column(db.String(128), unique=True, comment="邮箱地址") money = db.Column(db.Numeric(10, 2), default=0.0, comment="钱包") def __repr__(self): # 相当于django的__str__ return f"{self.name}<{self.__class__.__name__}>"class Course(db.Model): """课程模型""" __tablename__ = "tb_course" id = db.Column(db.Integer, primary_key=True, comment="主键") name = db.Column(db.String(255), unique=True, comment="课程") price = db.Column(db.Numeric(8, 2), comment="价格") def __repr__(self): # 相当于django的__str__ return f"{self.name}<{self.__class__.__name__}>"class Teacher(db.Model): """老师模型""" __tablename__ = "tb_teacher" id = db.Column(db.Integer, primary_key=True, comment="主键") name = db.Column(db.String(255), unique=True, comment="姓名") #枚举类型 option = db.Column(db.Enum("讲师", "助教", "班主任"), default="讲师") def __repr__(self): return f"{self.name}<{self.__class__.__name__}>"#在视图函数中实现增删改查@app.route("/data")def data(): """添加数据""" # # 添加一条数据 # student = Student( # name="小明", # age=17, # sex=True, # email="xiaoming@qq.com", # money=30.50 # ) # db.session.add(student) # db.session.commit() # # 添加多条数据 # student_list = [ # Student(name="小黑", age=16, sex=True, email="xiaohei2@qq.com", money=1000), # Student(name="小红", age=15, sex=False, email="xiaohong2@qq.com", money=1200), # Student(name="小兰", age=11, sex=True, email="xiaolan2@qq.com", money=600), # Student(name="小白", age=21, sex=False, email="xiaobai2@qq.com", money=2900), # ] # db.session.add_all(student_list) # db.session.commit() """更新操作""" # # 更新一条数据 # student = Student.query.get(3) # student.age = 18 # db.session.commit() # 更新多条数据 # Student.query.filter(Student.sex == True).update({ # Student.money: Student.age * 100, # }) # db.session.commit() """删除操作""" # # 删除一条数据 # student = Student.query.get(5) # db.session.delete(student) # db.session.commit() # # 删除多条数据 Student.query.filter(Student.sex==False).delete() db.session.commit() return "ok"if __name__ == '__main__': #要想执行创建表,需要调用db.creat_all(),db要想被调用,需要放到app上下文里面 with app.app_context(): # 如果没有提前声明模型中的数据表,则可以采用以下代码生成数据表, # 如果数据库中已经声明了有数据表,则不会继续生成 db.create_all() app.run(debug=True)
关于数据库锁
悲观锁,是属于数据库中的一种互斥锁机制,但是乐观锁并非真正的数据库锁。
2种锁都是数据库在应对并发操作时,防止出现资源抢夺的,基于不同人生观所实现2种解决方案。
悲观锁的基本使用:
>>> 数据库终端开始
begin; -- 开启事务select * from db_student where student_id = 5 for update; -- 添加一把更新锁【悲观锁】.... -- 在事务提交之前,任何第三方连接都不能修改 student_id = 5这条数据 update from db_student set age = 16 where student_id = 5;commit; -- 提交事务<<< 数据库终端开始
悲观锁的问题:
提前锁定数据,形成串行化,形成阻塞,不利于性能发挥,不适用高并发场景。悲观锁只能保证数据的一致性,不能保证脏数据的出现乐观锁的出现就是为了解决悲观锁的问题。
举例:双11活动,商城里面id=5的商品的库存num=10了,现在我们要基于乐观锁和悲观锁来解决下单过程中,出现的资源抢夺现象,避免出现超卖(商品数量不能为负数)。
乐观锁:
—> begin; 开启事务
—> 先查看库存,记录当前库存 original_num=10
—> 进行下单操作,买6件
—> 付款
—> 扣除库存 update goods set num=num-6 where num=original_num and id=5; # 增加更新条件,判断库存是否还是原来
如果执行成功,则表示没有人抢,购买成功
—> commit;
如果执行失败,则表示已经有人先抢购
—> rollback;
悲观锁:
—> begin; 开启事务
—> 先给id=5的数据,加锁
select * from goods where id=5 for update;
—> 进行下单操作,买6件
—> 付款
—> 扣除库存 update from goods set num=num-6 where id=5;
—> 执行成功解锁
—> commit; 提交事务
总结
本文详述了在flask项目中结合SQLAlchemy操作mysql数据库的详细用法,非常实用,感兴趣的朋友可以一键三连,flask的高阶用法持续更新中!!!