Flask DateBase
数据库配置
1 | # 主机名 |
准备数据库对象
SQLAlchemy
Flask框架支持使用SQLAlchemy进行数据库操作
直接根据app.config创建出db对象1 | db = SQLAlchemy(app) |
1 | db = SQLAlchemy() |
进行数据库连接测试:
1 | with app.app_context(): #拉取app上下文 |
migrate
1 | with app.app_context(): |
SQLAlchemy会将所有继承了 db.Model 的 ORM模型 映射成数据库表,
但这种自动化的映射仅限于表的首次创建(浅更新)
如果修改已存在表内部的结构,SQLAlchemy不会对已存表的数据库结构进行更新,
此处根据ORM模型进行数据库迁移更新的操作可以使用 flask_migrate 来实现
1 | from flask_migrate import Migrate |
1 | 1. 初始化数据库,仅执行一次 |
在执行完第1步,初始化数据库之后,会在项目根目录下新创建一个migrations文件,文件结构如下:
- versions
- 存放每次更新的数据库对应的更新命令(以版本号命名),支持根据数据库版本号进行回退操作
- alembic.ini : A generic, single database configuration.
- env.py : Alembic Config object
- README
- script.py.mako
创建ORM模型
ORM
- O Object 对象
- R Relationship 关系
- M Map 映射
ORM模型需要:
- 继承自db.Model
- 拥有表名属性 tablename
1 | class Book(db.Model): |
1 | class Authro(db.Model): |
ForeignKey && relationship
1 | db.ForeignKey("target_table.key_name") |
通过提供指定表的主键值,能够将对应的整条数据拉取过来,
相当于摇人时手机里的电话号码,比如希望John过来,只需要John的手机号码,
但是把John叫过来之后,需要给John流出一个座位安顿,
对应的,我们也需要为被拉取的数据提供一个存放的位置(甚至可以是其他表!)
1 | target_value = db.relationship("target_table_Model", back_populates="back_target_table") |
- 第一个参数代表目标表的ORM模型名称(字符串)
- back_populates 定义反向引用,用于建立双向关系
现在Book和Author是多对一的关系
Book中拉取对应author的信息,(这本书的作者是X君)
同时也需要在author中收集Books的信息,(X君写了A、B、C等书)
因此为了建立起多对一的关系,需要同时对两张表进行配置:
1 | class Book(db.Model): |
1 | class Author(db.Model): |
为了简化这种双向配置的操作,也可以直接使用backref进行反向聚集配置:
1 | class Book(db.Model): |
数据库关系配置
1 | class Writer(db.Model): |
1 | class Book(db.Model): |
1 | class Citizen(db.Model): |
1 | class City(db.Model): |
1 | class Country(db.Model): |
1 | class Capital(db.Model): |
}
1 | association_table = db.Table( |
1 | class Student(db.Model): |
1 | class Teacher(db.Model): |
基本数据库操作
需要写入数据库的操作都需要在最后进行commit提交
1 | db.session.commit() |
db.session.add
1 | book = Book(name=name, author_id=author) |
db.session.delete
1 | book = Book.query.get(id) |
1 | book = Book.query.get(id) |
Obj.query是继承自db.Model的属性,
查询需要调用ORM模型的query属性
get(primary_key) 通过主键查询
1 | book = Book.query.get() |
filter_by(key=value,…)
注意: filter_by()[0]和filter_by().first()的区别:
- filter_by[0] 为空时会报错
- filter_by().first() 为空时不会报错
1 | book = Book.query.filter_by(name=name) |