第4课_数据库关系和迁移
热度🔥:18 免费课程
授课语音
Flask 中的数据库关系和迁移
在开发复杂的 Web 应用时,数据库通常会涉及多个表之间的关系,例如一对多、多对多等。Flask-SQLAlchemy 提供了非常方便的 ORM(对象关系映射)机制来处理这些关系。同时,随着应用的不断发展,数据库模式(如表结构)的变更也成为开发中的重要部分。Flask-Migrate 扩展通过 Alembic 来实现数据库迁移,帮助我们在不丢失数据的情况下更新数据库结构。
本课将介绍如何在 Flask 中管理数据库的关系,如何在 Flask 应用中处理一对多、多对多等关系,以及如何使用 Flask-Migrate 来进行数据库迁移。
1. Flask 数据库关系
在关系型数据库中,表之间的关系常常是通过外键(Foreign Key)来实现的。Flask-SQLAlchemy 使用 Python 类来表示表之间的关系。
1.1 一对多(One-to-Many)关系
一对多关系是最常见的关系类型。例如,一个作者(Author)可以有多本书(Book),但一本书只能有一个作者。在 SQLAlchemy 中,可以使用 db.ForeignKey
和 db.relationship
来建立这种关系。
示例:作者和书籍的关系
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///example.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
class Author(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
books = db.relationship('Book', backref='author', lazy=True)
class Book(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
author_id = db.Column(db.Integer, db.ForeignKey('author.id'), nullable=False)
with app.app_context():
db.create_all()
if __name__ == '__main__':
app.run(debug=True)
1.2 代码解析
db.relationship('Book', backref='author', lazy=True)
:在Author
类中,定义了与Book
类的一对多关系。backref='author'
表示可以通过book.author
访问对应的作者。author_id = db.Column(db.Integer, db.ForeignKey('author.id'), nullable=False)
:在Book
类中,使用db.ForeignKey
来定义指向Author
类的外键。
关系操作
- 获取某个作者的所有书籍:
author = Author.query.first()
books = author.books # 获取该作者的所有书籍
- 获取某本书的作者:
book = Book.query.first()
author = book.author # 获取该书籍的作者
1.3 多对多(Many-to-Many)关系
多对多关系通常通过一个关联表来实现。比如,学生和课程之间可能是多对多的关系:一个学生可以选多门课程,一门课程也可以有多个学生。我们需要一个额外的表来维护这种关系。
示例:学生和课程的关系
class Student(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
courses = db.relationship('Course', secondary='enrollment', backref='students')
class Course(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
class Enrollment(db.Model):
student_id = db.Column(db.Integer, db.ForeignKey('student.id'), primary_key=True)
course_id = db.Column(db.Integer, db.ForeignKey('course.id'), primary_key=True)
1.4 代码解析
secondary='enrollment'
:在Student
类中,通过secondary
参数指定了多对多关系的关联表Enrollment
。backref='students'
:在Course
类中,使用backref
来创建反向关系,允许通过course.students
获取所有选修该课程的学生。
关系操作
- 获取学生选修的所有课程:
student = Student.query.first()
courses = student.courses # 获取该学生的所有课程
- 获取某门课程的所有学生:
course = Course.query.first()
students = course.students # 获取选修该课程的所有学生
2. Flask 数据库迁移
在开发过程中,数据库结构(如表的字段、关系等)经常会发生变化。手动修改数据库结构不仅容易出错,而且每次变更都可能需要手动更新大量的 SQL 脚本。Flask-Migrate 扩展可以帮助我们通过数据库迁移来管理这些变更。
2.1 安装 Flask-Migrate
Flask-Migrate 是基于 Alembic 实现的迁移扩展,它集成了 SQLAlchemy。首先,需要安装 Flask-Migrate:
pip install Flask-Migrate
2.2 配置 Flask-Migrate
在 Flask 应用中配置 Flask-Migrate 非常简单。您只需要初始化 Migrate
对象并将其与 Flask 和 SQLAlchemy 结合。
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///example.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
migrate = Migrate(app, db)
2.3 初始化迁移
在项目的根目录下,您可以通过命令行工具进行迁移操作。首先,初始化迁移环境:
flask db init
这将在项目目录下创建一个 migrations
文件夹,Flask-Migrate 会在其中存储迁移脚本。
2.4 生成迁移文件
每当您修改了模型类(如添加字段、修改字段等),可以生成迁移脚本:
flask db migrate -m "Add new field to User model"
该命令会自动检查模型类与数据库结构之间的差异,并生成一个迁移脚本。
2.5 应用迁移
生成迁移脚本后,您需要应用迁移以更新数据库结构:
flask db upgrade
此命令会将迁移脚本应用到数据库中,更新数据库结构。
2.6 回滚迁移
如果您在迁移后遇到问题,可以使用 flask db downgrade
来回滚迁移:
flask db downgrade
此命令会将数据库结构回滚到上一个版本。
3. 数据库迁移示例
假设我们需要在 User
表中添加一个 age
字段。以下是更新步骤:
- 修改模型类,添加新的字段:
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(100), unique=True, nullable=False)
age = db.Column(db.Integer) # 新增字段 age
- 生成迁移脚本:
flask db migrate -m "Add age field to User model"
- 应用迁移:
flask db upgrade
- 验证数据库:
user = User.query.first()
print(user.age) # 验证新字段是否添加成功
4. 总结
通过本课的学习,您掌握了在 Flask 中使用 SQLAlchemy 处理数据库表之间的关系,包括一对多和多对多关系。您还学会了如何使用 Flask-Migrate 扩展来进行数据库迁移,帮助您轻松管理数据库结构的变更。
数据库关系和迁移是构建 Web 应用时非常重要的内容,理解并掌握这些概念将帮助您高效地管理和扩展应用的数据层。