一、基本使用
1.安装 Flask-SQLAlchemy
pip install Flask-SQLAlchemy
2.安装 Flask-Migrate (数据库迁移)
pip install Flask-Migrate
3.引入
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from config import Config
app = Flask(__name__, template_folder='templates', static_folder="", static_url_path="")
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql://root:root@127.0.0.1:3306/testdb?charset=utf8mb4"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SQLALCHEMY_POOL_RECYCLE'] = 1
db = SQLAlchemy(app)
migrate = Migrate(app, db)
4.创建model
from app import db
class Test(db.Model):
__tablename__ = 'test' # 可以不加,不加的话默认表名跟类名一样(小写),
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='主键')
name = db.Column(db.String(255), comment="string类型")
text_str = db.Column(db.Text, default="", comment="text类型")
create_time = db.Column(db.DateTime, default=datetime.datetime.now, comment='创建时间')
创建完成后 依次执行
初始化(第一次需要执行,后面不需要):flask db init
检测更新的mode: flask db migrate
添加mode到数据库: flask db upgrade
5.新增
# 新增单个
db.session.add(Test(name="张三"))
db.session.commit()
# 多个
db.session.add_all([Test(name="张三"),Test(name="李四")])
db.session.commit()
6.修改
# 第一种方式: 查询出来再改
test = Test.query.filter(Test.id = 1).first()
test.name = "李四"
db.session.commit()
# 第二种方式: 直接update 无需commit
Test.query.filter(Test.id == 1).update({'name':'李四','text_str':'abcd'})
7.删除
# 第一种方式: 查询出来再删除
test = Test.query.filter(Test.id = 1).first()
db.session.delete(test)
db.session.commit()
# 第二种方式: 直接delete
Test.query.filter(Test.id == 1).delete()
8.查询
# 单个查询
test = Test.query.fitler(Test.id == 1).first()
print(test)
test2 = Test.query.get(1)
print(test2)
# 多个查询
all = Test.query.all()
# 带条件带排序带分组的带分页的查询
q = Test.query
q = q.with_entities(Test.name,Test.create_time) #只查询某几个字段
q = q.filter(Test.name.like('%张%')) # 带条件
q = q.order_by(Test.create_time.desc()) # 排序 时间倒序
q = q.group_by(Test.name) # 分组
q = q.paginate(page=1, per_page=10, error_out=False) # 分页 page页码 1页 per_page每页多少条 10条
pages = q.pages # 总页数
total = q.total # 总条数
items = q.items # 数据集
for item in items:
print(item)
# 查询有多条
count = Test.query.fitler(Test.id == 1).count()
print(count)
二、偶尔会遇到的一些情况
1.新增的时候 你还不想commit 但是你想得到id你就可以这么写
t = Test(name='张三')
db.session.add(t)
db.flush()
print(t) # 这个时候 无需commit就可以得到 id
# 例如,当你有一个 model User 和一个model UserRole
class User(db.Model):
user_id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment="用户id")
username = db.Column(db.String(255), comment="用户账号")
password = db.Column(db.String(255), comment="密码")
class UserRole(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment="id")
user_id = db.Column(db.Integer, comment="用户id")
role_id = db.Column(db.Integer, comment="角色id")
# 你想新增一个用户的然后给她角色1
u1 = User(username='张三')
db.session.add(u1)
db.flush()
r1 = UserRole(user_id = u1.user_id,
role_id = 1)
db.session.add(u1)
try:
db.session.commit() # 还是得提交,一定要记住!!
except:
db.session.rollback()
# 这样,如果出错了就可以直接全部回滚
# 有时候会在 for循环中用到
for i in range(10):
u1 = User(username=f'张三{i}')
db.session.add(u1)
db.flush() # 刷到内存中,但是还没提交事务 rollback会直接清理掉
r1 = UserRole(user_id = u1.user_id,
role_id = 1)
db.session.add(u1)
try:
db.session.commit()
# 只要这里没提交就不会写入数据库
except:
db.session.rollback()
2. 异步任务 celery中 出现 MySQL server has gone away 或者是 异步任务执行一段时间出现数据库错误的情况 重启一下又好了那种(我遇到过)这种情况一般是mysql连接不够或者mysql连接被占用太多了
这种情况就需要异步执行完后移除session
@task_postrun.connect
def close_session(*args, **kwargs):
db.session.remove()
print("刚刚执行了异步任务,已关闭db连接")
一般写在init的地方
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from config import Config
# 异步任务执行完成后关闭数据库连接
@task_postrun.connect
def close_session(*args, **kwargs):
db.session.remove()
print("刚刚执行了异步任务,已关闭db连接")
app = Flask(__name__, template_folder='templates', static_folder="", static_url_path="")
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql://root:root@127.0.0.1:3306/testdb?charset=utf8mb4"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SQLALCHEMY_POOL_RECYCLE'] = 1
db = SQLAlchemy(app)
migrate = Migrate(app, db)