flask数据库表升级

 

依赖库

  • flask
  • flask-migrate
  • flask-sqlalchemy

相关代码

# extensions/ext_db.py
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def init(app):
    db.init_app(app)
# extensions/ext_migrate.py
import flask_migrate

def init(app, db):
    flask_migrate.Migrate(app, db)
# app.py
from flask import Flask

from extensions import ext_db, ext_migrate

app = Flask(__name__)
# 需要配置数据库信息
app.config.from_mapping({"SQLALCHEMY_DATABASE_URI": "sqlite:///my-local-db"})
# 注册数据库
ext_db.init(app)
# 注册数据库表迁移
ext_migrate.init(app, ext_db.db)

# 启动服务
app.run(host='0.0.0.0', port=8088)
# models/mytable.py
from extensions.ext_db import db

class MyTable(db.Model):
    __tablename__ = "mytable"
    __table_args__ = (db.PrimaryKeyConstraint('my_id', name='mytable_pkey'),)

    my_id = db.Column(db.String(32), nullable=False)

使用

  • 初始化
poetry run python -m flask db init
  • 编辑script.py.mako,导入项目的db模块
from alembic import op
import sqlalchemy as sa
# 在这里添加
from myrepo import db_models
${imports if imports else ""}
  • 编辑env.py,修改默认的管理版本的表名,避免不同项目的migration互相冲突(可选)
def run_migrations_offline():
    url = config.get_main_option("sqlalchemy.url")
    context.configure(
        url=url,
        target_metadata=get_metadata(),
        # 在这里修改
        version_table="t_myrepo_distinct_alembic_version",
        literal_binds=True,
    )

    with context.begin_transaction():
        context.run_migrations()

def run_migrations_online():

    def process_revision_directives(context, revision, directives):
        if getattr(config.cmd_opts, 'autogenerate', False):
            script = directives[0]
            if script.upgrade_ops.is_empty():
                directives[:] = []
                logger.info('No changes in schema detected.')

    conf_args = current_app.extensions['migrate'].configure_args
    if conf_args.get("process_revision_directives") is None:
        conf_args["process_revision_directives"] = process_revision_directives

    connectable = get_engine()

    with connectable.connect() as connection:
        context.configure(
            connection=connection,
            target_metadata=get_metadata(),
            # 在这里修改
            version_table="t_myrepo_distinct_alembic_version",
            **conf_args
        )

        with context.begin_transaction():
            context.run_migrations()
  • 将表的升级/降级方式写到新的version文件中
poetry run python -m flask db migrate -m "my migration"
  • 将表的升级/降级方式实际作用于数据库
poetry run python -m flask db upgrade

忽略部分表的初始化

# env.py
IGNORE_TABLES = ["table1", "table2"]

def include_object_fn(object, name, type_, reflected, compare_to):
    # return False代表忽略此表
    if type_ == "table" and name in IGNORE_TABLES:
        return False
    return True

# ...

# 以防万一,在run_migrations_offline和run_migrations_online函数下都要进行修改
        context.configure(
            connection=connection,
            target_metadata=get_metadata(),
            version_table="t_myrepo_distinct_alembic_version",
            # 在这里添加
            include_object=include_object_fn,
            **conf_args
        )

注意点

如果是sqlite,执行命令的目录应当保持一致,确保更新到同一个数据库文件中