当前位置: 首页 > news >正文

Flask高效数据库操作指南

Flask-SQLAlchemy 数据库操作

关于Flask数据库

Flask中没有指定使用的数据库,可以自由选择不管你是使用关系型数据库,还是非关系型数据库都可以,不像django提供了orm 数据库抽象层,可以直接采用对象的方式操作数据库。但是为了开发效率,在开发Flask项目中我们一般会选择 SQLALchemy 来操作数据库,类似于Django的ORM。SQLALchemy实际上是对数据库的抽象,让开发者不直接使用sql语句做开发,而是通过Python对象来操作数据库,在舍弃一些性能开销的同时,换来的是开发效率的较大提升。

SQLAlchemy是一个关系型数据库框架,它提供了高层的ORM和底层的原生数据库的操作。为了简化配置和操作,我们使 Flask-SQLAlchemy,这个 Flask 扩展封装了 SQLAlchemy 框架。

安装 Flask-SQLAlchemy

pip install Flask-SQLAlchemy

要连接mysql数据库还需要安装flask-mysqldb

pip install flask-mysqldb

如果安装报下面错误

Command "python setup.py egg_info" failed with error code 1

请先安装执行下面这条命令:(Linux)

sudo apt-get install mysql-server libmysqld-dev

示例:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
​
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:xxxxxx@127.0.0.1/flask01'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True  # 追踪对象的修改并且发送信号
db = SQLAlchemy(app)
​
class User(db.Model):# SQLAlchemy 需要手动执行主键列,第一个参数是 字段类型,第二个参数是约束条件id = db.Column(db.Integer,primary_key=True)name = db.Column(db.String(20),unique=True)
​
if __name__ == '__main__':with app.app_context():  # 添加应用上下文# 创建所有表db.create_all()

1. 数据库连接配置

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
​
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/py'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True  # 追踪对象的修改并且发送信号
db = SQLAlchemy(app)

配置键说明

配置键说明
SQLALCHEMY_DATABASE_URI设置连接数据库<br>格式:mysql://username:password@server/db
SQLALCHEMY_BINDS一个映射绑定 (bind) 键到 SQLAlchemy 连接 URIs 的字典。更多的信息请参阅 绑定多个数据库。
SQLALCHEMY_ECHO如果设置成 True,SQLAlchemy 将会记录所有 发送 标准输出(stderr)的语句,这对调试很有帮助。
SQLALCHEMY_RECORD_QUERIES可以用于显式地禁用或者启用查询记录。查询记录 在调试或者测试模式下自动启用。更多信息请参阅 get_debug_queries()。
SQLALCHEMY_NATIVE_UNICODE可以用于显式地禁用支持原生的 unicode。这是 某些数据库适配器必须的(像在 Ubuntu 某些版本上 的 PostgreSQL),当使用不合适的指定无编码的数 据库 默认值时。
SQLALCHEMY_POOL_SIZE数据库连接池的大小、默认是数据库引擎的默认值 (通常是 5)。
SQLALCHEMY_POOL_TIMEOUT指定数据库连接池的超时时间。默认是 10。
SQLALCHEMY_POOL_RECYCLE自动回收连接的秒数。这对 MySQL 是必须的,默认 情况下 MySQL 会自动移除闲置 8 小时或者以上的连 接。需要注意的是如果使用 MySQL 的话,Flask-SQLAlchemy 会自动地设置这个值为 2 小时。
SQLALCHEMY_MAX_OVERFLOW控制在连接池达到最大值后可以创建的连接数。当这 些额外的连接回收到连接池后将会被断开和抛弃。
SQLALCHEMY_TRACK_MODIFICATIONS如果设置成 True (默认情况),Flask-SQLAlchemy 将 会追踪对象的修改并且发送信号。这需要额外的内 存,如果不必要的可以禁用它。
SQLALCHEMY_COMMIT_ON_TEARDOWN每次请求结束后会自动提交数据库中的改动

数据库URI格式

数据库URI格式
MySQLmysql://username:password@hostname/database
Postgrespostgresql://username:password@hostname/database
SQLite (Unix)sqlite:////python/data/database
SQLite (Windows)sqlite:///c:/db/data/database
Oracleoracle://scott:tiger@127.0.1:1521/sidname

字段说明: username:登录数据库的用户名 password:登录数据库的密码 hostname:服务器主机 ip,可以是本地主机(localhost)也可以是远程服务器 database:表示要使用的数据库


2. 模型类定义

字段类型

类型名Python中类型说明
Integerint普通整数,一般是32位
SmallIntegerint小整数
BigIntegerint或long大整数
Floatfloat浮点数
Numericdecimal.Decimal普通整数,一般是32位
Stringstr变长字符串
Textstr变长字符串,对较长或不限长度的字符串做了优化
Unicodeunicode变长Unicode字符串
UnicodeTextunicode变长Unicode字符串,对较长或不限长度的字符串做了优化
Booleanbool布尔值
Datedatetime.date时间
Timedatetime.datetime日期和时间
LargeBinarystr二进制文件

约束条件

约束说明
primary_key主键
unique唯一约束,True不允许重复
index索引,如果为True,为这列创建索引,提高查询效率
nullable空值,如果为True,允许有空值,如果为False,不允许有空值
default默认值

关系类型

关系说明
One To Many(一对多)表示一对多的关系时,在子表类中通过 foreign key (外键)引用父表类,在父表类中通过 relationship() 方法来引用了表的类
One To One(一对一)一对一是两张表之间本质上的双向关系。只需要在一对多关系基础上的父表中使用 uselist=False 参数来表示
Many To Many(多对多)多对多关系会在两个类之间增加一个关联的表,连个关系表中使用 relationship() 方法中通过 secondary 来引用关联表,关联表通过 MetaData 对象与声明基类关联,使用ForeignKey 连接接来定位到远程的表

3. 关系模型

一对多关系
class Father(db.Model):"""创建一个父表模型类"""# 表名__tablename__ = 'father'# id主键列,整数类型,自增id = db.Column(db.Integer, primary_key=True)# name,可变长字符串类型name = db.Column(db.String(20))# 关系字段,不是数据库中真实存在的字段,而是为了方便查询添加的属性son = db.relationship('Son', backref='father')
​
class Son(db.Model):"""创建一个子表模型类"""# 表名__tablename__ = 'son'# id主键列,整数类型,自增id = db.Column(db.Integer, primary_key=True)# name,可变长字符串类型name = db.Column(db.String(20))# 外键,需要指定字段类型,以及关联那个表的那个字段father_id = db.Column(db.Integer, db.ForeignKey('father.id'))
一对一关系
class Father(db.Model):"""创建一个父类模型类"""# 表名__tablename__ = 'father'# id主键列,整数类型,自增id = db.Column(db.Integer, primary_key=True)# name,可变长字符串类型name = db.Column(db.String(20))# 关系字段,不是数据库中真实存在的字段,而是为了方便查询添加的属性son = db.relationship('Son', backref='father', uselist=False)
​
class Son(db.Model):"""创建一个子表模型类"""# 表名__tablename__ = 'son'# id主键列,整数类型,自增id = db.Column(db.Integer, primary_key=True)# name,可变长字符串类型name = db.Column(db.String(20))# 外键,需要指定字段类型,以及关联那个表的那个字段father_id = db.Column(db.Integer, db.ForeignKey('father.id'))
多对多关系
# 多对多关系中的两个表之间的一个关联表
association_table = db.Table('association', db.metadata,db.Column('author_id', db.Integer, db.ForeignKey('author.id')),db.Column('book_id', db.Integer, db.ForeignKey('book.id'))
)
​
class Author(db.Model):"""创建作者模型类"""# 指定表名,如果没有指定将默认使用模型类的名称__tablename__ = 'author'# id 类型是整数 主键列id = db.Column(db.Integer, primary_key=True)# name 类型是可变长字符串,唯一name = db.Column(db.String(20), unique=True)# 关联中间表,不是数据库中真实存在的字段,而是为了方便查询添加的属性book = db.relationship('Book', back_populates='author',secondary=association_table)
​
class Book(db.Model):"""创建书模型类"""# 指定表名,如果不指定将使用模型类名称作为表名__tablename__ = 'book'id = db.Column(db.Integer, primary_key=True)name = db.Column(db.String(20))# 关联中间表,不是数据库中真实存在的字段,而是为了方便查询添加的属性author = db.relationship("Author", secondary=association_table,back_populates="book")

4. 数据操作

创建表

if __name__ == '__main__':# 删除所有表,注意这条是危险命令,会将模型类对应数据库中的表物理删除。在实际生产环境下勿用。db.drop_all()# 创建所有表db.create_all()

添加数据

# 创建一个 father对象
f = Father(name='小头爸爸')
# 将数据添加到会话
db.session.add(f)
# 提交会话数据
db.session.commit()
​
# 创建两个Son对象,这里利用到father对象id,需要先将Father对象提交才能拿到id
s = Son(name='大头儿子', father_id=f.id)
s1 = Son(name='中头儿子', father_id=f.id)
# 同时添加多个数据,接收一个列表做参数
db.session.add_all([s, s1])
# 提交会话数据
db.session.commit()

事务管理

# 创建一个 mother
m = Father(name='围裙妈妈')
db.session.add(m)
​
# 创建了一个妈妈,但是我们这里是Father类,需要回滚会话
db.session.rollback()

删除数据

# 删除演员表中的'吴孟达'
# 将数据查询出来
actor = Cast.query.filter(Cast.name=='吴孟达').first()
# 删除对象
db.session.delete(actor)
# 提交到数据库
db.session.commit()

更新数据

# 第一种方式:查询后修改
# 先将'梁小龙'查询出来
actor = Cast.query.filter(Cast.name=='梁小龙').first()
# 将'梁小龙'的名字改成'火云邪神'
actor.name = '火云邪神'
db.session.add(actor)
db.session.commit()
​
# 第二种方式:update方式
# 将'朱茵'修改成'紫霞仙子'
Cast.query.filter(Cast.name=='朱茵').update({'name':'紫霞仙子'})
db.session.commit()

5. 数据查询

基本查询方法

方法作用
all()返回数据库中所有数据,列表形式返回
first()返回查询的第一个结果,如果未查到,返回None
first_or_404()返回查询的第一个结果,如果未查到,返回404
get()返回指定主键对应的行,如不存在,返回None
get_or_404()返回指定主键对应的行,如不存在,返回404
count()返回查询结果的数量
paginate()返回一个Paginate对象,它包含指定范围内的结果

查询过滤器

过滤器说明
filter()把过滤器添加到原查询上,返回一个新查询
filter_by()把等值过滤器添加到原查询上,返回一个新查询
limit使用指定的值限定原查询返回的结果
offset()偏移原查询返回的结果,返回一个新查询
order_by()根据指定条件对原查询结果进行排序,返回一个新查询
group_by()根据指定条件对原查询结果进行分组,返回一个新查询

查询示例

# filter_by 精确匹配查询,条件只能是本表的字段
Cast.query.filter_by(name='周星驰').all()
​
# first()返回查询到的第一个对象
Cast.query.first()
​
# all()返回查询到的所有对象
Cast.query.all()
​
# filter 模糊查询
Cast.query.filter(Cast.name.startswith('周'))
Cast.query.filter(Cast.name.endswith('龙'))
Cast.query.filter(Cast.name=='周星驰').all()
​
# like 正则模糊匹配
Cast.query.filter(Cast.name.like('周%%'))

逻辑运算查询

from sqlalchemy import and_, or_, not_
​
# 查询名字为'周星驰'并且movie_id为2的演员数据
cast.query.filter(and_(cast.name=='周星驰', cast.movie_id==2)).all()
​
# 查询名字为'周星驰'或者id为2的演员数据
cast.query.filter(or_(cast.name=='周星驰', cast.movie_id==2)).all()
​
# 查询名字不为'周星驰'的演员
cast.query.filter(not_(cast.name=='周星驰')).all()

关联查询

# 查询名字为朱茵的演员,并且查出她出演的电影
# 查询出演员'朱茵'
actor = Cast.query.filter(Cast.name=='朱茵').all()
# 直接通过 relationship 中定义的 backref 属性可以直接查询出演员对应的电影
movie = actor[0].Movie
# 通过电影直接查询出所有演员
actors = movie.cast

添加repr方法

def __repr__(self):return "Father: %s" % self.name

6. 完整示例

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
​
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@192.168.20.233:3306/py'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
​
class Movie(db.Model):"""创建一个电影模型类"""# 表名__tablename__ = 'movie'# id主键列,整数类型,自增id = db.Column(db.Integer, primary_key=True)# name,可变长字符串类型name = db.Column(db.String(20))# 关系字段,不是数据库中真实存在的字段,而是为了方便查询添加的属性cast = db.relationship('Cast', backref='Movie')def __repr__(self):return "Movie: %s " % self.name
​
class Cast(db.Model):"""演员模型类"""# id主键列,整数类型,自增id = db.Column(db.Integer, primary_key=True)# name,可变长字符串类型name = db.Column(db.String(20))# 外键关联idmovie_id = db.Column(db.Integer, db.ForeignKey('movie.id'))def __repr__(self):return "Cast: %s " % self.name
​
if __name__ == '__main__':# 删除所有表db.drop_all()# 创建所有表db.create_all()# 创建电影数据m1 = Movie(name='大话西游')m2 = Movie(name='功夫')db.session.add_all([m1, m2])db.session.commit()# 创建演员数据cast_list = []for i in ['周星驰','朱茵','吴孟达','莫文蔚']:c = Cast(name=i, movie_id=m1.id)cast_list.append(c)for i in ['周星驰','梁小龙','元华']:c = Cast(name=i, movie_id=m2.id)cast_list.append(c)db.session.add_all(cast_list)db.session.commit()

http://www.lryc.cn/news/626679.html

相关文章:

  • 面向AI应用的新一代迷你电脑架构解析 ——Qotom Q51251AI
  • 【39页PPT】大模型DeepSeek在运维场景中的应用(附下载方式)
  • imx6ull-驱动开发篇31——Linux异步通知
  • Jumpserver堡垒机使用VNC录入Linux图形界面资产
  • 十大经典 Java 算法解析与应用
  • 机器学习--数据清洗—(续篇)
  • (nice!!!)(LeetCode 每日一题) 1277. 统计全为 1 的正方形子矩阵 (动态规划)
  • C++ MFC/BCG编程:文件对话框(CFileDialog、CFolderPickerDialog)
  • 力扣48:旋转矩阵
  • 数据结构之排序大全(1)
  • 2.Shell脚本修炼手册之---创建第一个 Shell 脚本
  • 大模型入门实战 | 单卡 3090 十分钟完成 Qwen2.5-7B 首次微调
  • 电脑驱动免费更新? 这款驱动管理工具:一键扫更新,还能备份恢复,小白也会用~
  • c语言多任务处理(并发程序设计)
  • iOS App 混淆工具实战 医疗健康类 App 的安全与合规保护
  • Elasticsearch 写入全链路:从单机到集群
  • [系统架构设计师]面向服务架构设计理论与实践(十五)
  • [element-plus] el-tree 拖拽到其他地方,不拖拽到树上
  • Vue3 element ui 给表格的列设置背景颜色
  • 晨控EtherCAT设备分配IP操作手册
  • LWIP的TCP协议
  • 在 Golang 中复用 HTTP 连接
  • 26_基于深度学习的茶叶等级检测识别系统(yolo11、yolov8、yolov5+UI界面+Python项目源码+模型+标注好的数据集)
  • CTFshow系列——命令执行web38-40
  • Qt音乐播放器项目实践:本地持久化与边角问题处理
  • 小红书账号隔离:解决IP关联问题方案
  • 网络工程师考试重点:OSI七层模型TCP/IP四层模型解析
  • 【北京迅为】iTOP-4412精英版使用手册-第三十二章 网络通信-TCP套字节
  • yolo_RK3588系列(三)
  • 5.4 4pnpm 使用介绍