flask_migrate---处理 sqlalchemy 数据迁移的工具

1. 什么是flask_migrate

flask_migrate 是专门用来做sqlalchemy 数据迁移的工具,当据模型发生变化的时可将修改后的模型重新映射到数据库中,这意味着数据库也将被修改。

本文介绍flask_migrate如何在flask项目中使用,所依赖的第三方库和版本信息如下

pip install flask==1.1.4
pip install flask-script==2.0.6
pip install flask_migrate==2.7.0
pip install sqlalchemy==1.4.22

2. 项目结构说明

本文用最小的项目结构来展示flask_migrate如何使用

一共有4个python需要编写,在project目录下有app.py, config.py,models.py, 和project同级目录下需要编写manager.py

config.py

from pathlib import Path

DATABASE = "migrate.db"
basedir = Path(__file__).resolve().parent
class Config():
    SQLALCHEMY_DATABASE_URI = f"sqlite:///{Path(basedir).joinpath(DATABASE)}"
    SQLALCHEMY_COMMIT_ON_TEARDOWN = True
    SECRET_KEY = 'secret key to protect from csrf'


    @staticmethod
    def init_app(app):
        pass

config.py 是flask项目的配置脚本,为了方便演示,我使用sqlite数据库,SQLALCHEMY_DATABASE_URI是数据的URI配置,sqlalchemy将根据这个配置选择用哪个第三方库作为引擎。

app.py

from flask import Flask
from project.config import Config
from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__)
app.config.from_object(Config)

db = SQLAlchemy()
Config.init_app(app)
db.init_app(app)

from project.models import *

@app.route('/')
def index():
    admin = db.session.query(User).filter(User.username =='admin').first()
    if admin is None:
        return {'status': 0, 'data': {}}
    else:
        print(admin.name_cn)
        return {'status': 1, 'data': {'username': admin.username, 'name_cn': admin.name_cn}}

app.py完成项目的初始化工作,同时提供了一个视图函数index,在index中将会返回管理员的信息。

models.py

from project.app import db
from sqlalchemy import Column, String, Integer
from werkzeug.security import generate_password_hash


class User(db.Model):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True, autoincrement=True)
    username = Column(String(50), nullable=False)
    password = Column(String(80), nullable=False)
    name_cn = Column(String(20), nullable=False)

    @classmethod
    def add_admin(cls):
        user = db.session.query(User).filter(User.username =='admin').first()
        if user is None:
            user = User(username='admin', password=generate_password_hash('123456'), name_cn='管理员')
            db.session.add(user)
            db.session.commit()

models.py 存放数据库模型,我只定义了一个user表,add_admin方法会向表中添加一个管理员。

manager.py

from flask_script import Manager, Server
from flask_migrate import MigrateCommand, Migrate, upgrade
from project.app import app, db
from project.models import *

manager = Manager(app)
migrate = Migrate(app, db)
# 子命令  MigrateCommand 包含三个方法 init migrate upgrade
manager.add_command('db', MigrateCommand)
manager.add_command('start', Server(host="0.0.0.0", port=8000, use_debugger=True))  # 创建启动命令


@manager.command
def deploy():
    upgrade()
    User.add_admin()


if __name__ == '__main__':
    manager.run()

manager.py 负责管理项目,除了管理数据库,还有server的启动命令start和我自己创建的数据库部署命令deploy。

3. 使用方法

flask_migrate 提供了很多命令,其中最为常用的是init, migrate, upgrade,第一次将数据模型映射到数据库中时,依次执行下面三个命令

python manager.py db init
python manager.py db migrate
python manager.py db upgrade

在这以后,如果数据模型发生了变化,只需要执行migrate 和 upgrade。

执行完上述命令后,此时user表里还没有数据,执行命令

python manager.py deploy

会执行deploy函数,向user表中写入一条管理员数据,在项目初始阶段,个别的表需要预置一些数据,项目才能正常运行,这样做也可以方便测试。

最后执行命令

python manager.py start

会启动flask 服务,在浏览器里访问http://127.0.0.1:8000/ 得到如下响应

{
  "data": {
    "name_cn": "\u7ba1\u7406\u5458", 
    "username": "admin"
  }, 
  "status": 1
}

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案