以 sqlite + SQLAlchemy 为案例,基于 flask 完成对数据库的连接、操作数据库、操作表记录。
使用 SQLAlchemy 操作数据库
SQLAlchemy——一个 Python 数据库工具(ORM,即对象关系映射)。
通过定义模型类(python代码的类)来表示数据库的表,flask 有很多第三方扩展,选择 flask-sqlalchemy
扩展集成 SQLAlchemy
安装环境
mkdir 3-flask-db-sqlalchemy
#创建虚拟环境
python -m venv venv
#激活虚拟环境
./venv/Scripts/activate
安装依赖
要同时安装 flask-sqlalchemy 和 sqlalchemy
pip install flask==2.3.3
pip install flask-sqlalchemy==2.5.1 sqlalchemy==1.4.47
提示 Flask-SQLAlchemy 3.x / SQLAlchemy 2.x 版本有一些大的变化,所以这里固定安装 2.5.1 和 1.4.47 版本。
配置数据库并初始化
数据库 URI: sqlite 的绝对路径,根目录下/data.db
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import sqlalchemy as sa
import os
import sys
WIN= sys.platform.startswith("win")
if WIN:
prefix = "sqlite:///"
else:
prefix = "sqlite:////"
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = prefix + os.path.join(app.root_path , 'data.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # 关闭对模型修改的监控
# 在扩展类实例化前加载配置
db = SQLAlchemy(app)
定义数据库模型
db 是前一步实例化的变量。由于db.Column
db.Integer
没有提示,改为手动引入 sqlalchemy 。
import sqlalchemy as sa
class User(db.Model):
id = sa.Column(sa.Integer, primary_key=True) # 主键
name = sa.Column(sa.String(20)) # 名字
class Movie(db.Model):
id = sa.Column(sa.Integer, primary_key=True) # 主键
title = sa.Column(sa.String(60)) # 电影标题
year = sa.Column(sa.String(4)) # 电影年份
模型类要声明继承
db.Model
在
db.Column()
中添加额外的选项(参数)可以对字段进行设置。比如,primary_key
设置当前字段是否为主键。除此之外,常用的选项还有nullable
(布尔值,是否允许为空值)、index
(布尔值,是否设置索引)、unique
(布尔值,是否允许重复值)、default
(设置默认值)等。每一个类属性(字段)要实例化
db.Column
,传入的参数为字段的类型,下面的表格列出了常用的字段类。| 字段类 | 说明 |
| ---------------- | ----------------------------------------------- |
| db.Integer | 整型 |
| db.String (size) | 字符串,size
为最大长度,例如db.String(20)
|
| db.Text | 长文本 |
| db.DateTime | 时间日期,Pythondatetime
对象 |
| db.Float | 浮点数 |
| db.Boolean | 布尔值 |
数据库操作
创建数据库
db.create_all() #如果没有就,创建数据库表,有的话就不执行
更新表结构
注意:
drop_all()
会删除所有数据
#你改动了模型类,想重新生成表模式,需要先执行删除,再创建。
db.drop_all() #注意:会删除所有数据
db.create_all()
表记录插入
分为三个步骤
创建记录
添加到会话
提交会话
User
Movie
为上面建立的模型类
user = User(name='Grey Li') # 创建一个 User 记录
m1 = Movie(title='Leon', year='1994') # 创建一个 Movie 记录
m2 = Movie(title='Mahjong', year='1996') # 再创建一个 Movie 记录
db.session.add(user) # 把新创建的记录添加到数据库会话
db.session.add(m1)
db.session.add(m2)
db.session.commit() # 提交数据库会话,只需要在最后调用一次即可
提示 在实例化模型类的时候,我们并没有传入
id
字段(主键),因为 SQLAlchemy 会自动处理这个字段。
最后一行 db.session.commit()
很重要,只有调用了这一行才会真正把记录提交进数据库,前面的 db.session.add()
调用是将改动添加进数据库会话(一个临时区域)中。
表记录查询
查询语句语法
<模型类>.query.<过滤方法(可选)>.<查询方法>
过滤方法
过滤方法 | 说明 |
---|---|
filter() | 使用指定的规则过滤记录,返回新产生的查询对象 |
filter_by() | 使用指定规则过滤记录(以关键字表达式的形式),返回新产生的查询对象 |
order_by() | 根据指定条件对记录进行排序,返回新产生的查询对象 |
group_by() | 根据指定条件对记录进行分组,返回新产生的查询对象 |
查询方法
查询方法 | 说明 |
---|---|
all() | 返回包含所有查询记录的列表 |
first() | 返回查询的第一条记录,如果未找到,则返回 None |
get(id) | 传入主键值作为参数,返回指定主键值的记录,如果未找到,则返回 None |
count() | 返回查询结果的数量 |
first_or_404() | 返回查询的第一条记录,如果未找到,则返回 404 错误响应 |
get_or_404(id) | 传入主键值作为参数,返回指定主键值的记录,如果未找到,则返回 404 错误响应 |
paginate() | 返回一个 Pagination 对象,可以对记录进行分页处理 |
User
Movie
为上面建立的模型类
movie = Movie.query.first() # 获取 Movie 模型的第一个记录(返回模型类实例)
print(movie.title)
Movie.query.all() # 获取 Movie 模型的所有记录,返回包含多个模型类实例的列表
Movie.query.count() # 获取 Movie 模型所有记录的数量
Movie.query.get(1) # 获取主键值为 1 的记录
Movie.query.filter_by(title='Mahjong').first() # 获取 title 字段值为 Mahjong 的记录
Movie.query.filter(Movie.title=='Mahjong').first() # 等同于上面的查询,但使用不同的过滤方法
提示 我们在说 Movie 模型的时候,实际指的是数据库中的 movie 表。表的实际名称是模型类的小写形式(自动生成),如果你想自己指定表名,可以定义
__tablename__
属性。
对于最基础的 filter()
过滤方法,SQLAlchemy 支持丰富的查询操作符,具体可以访问文档相关页面查看。除此之外,还有更多的查询方法、过滤方法和数据库函数可以使用,具体可以访问文档的 Query API 部分查看。
表记录更新
movie = Movie.query.get(2)
movie.title = 'WALL-E' # 直接对实例属性赋予新的值即可
movie.year = '2008'
db.session.commit() # 注意仍然需要调用这一行来提交改动
表记录删除
movie = Movie.query.get(1)
db.session.delete(movie) # 使用 db.session.delete() 方法删除记录,传入模型实例
db.session.commit() # 提交改动