使用Flask-Migrate迁移数据库

在开发时,以删除表再重建的方式更新数据库简单直接,但明显的缺陷是会丢掉数据库中的所有数据。在生产环境下,没有人想把数据都删除掉,这时需要使用数据库迁移工具来完成这个工作。SQLAlchemy的开发者Michael Bayer写了一个数据库迁移工作—Alembic来帮助我们实现数据库的迁移,数据库迁移工具可以在不破坏数据的情况下更新数据库表的结构。蒸馏器(Alembic)是炼金术士最重要的工具,要学习SQL炼金术(SQLAlchemy),当然要掌握蒸馏器的使用。

扩展Flask-Migrate继承了Alembic,提供了一些flask命令来简化迁移工作,我们将使用它来迁移数据库。Flask-Migrate及其依赖(主要是Alembic)可以使用pipenv安装:

(Lenovo-ezd1lI9Y) C:\Users\Lenovo>pipenv install flask-migrate

在程序中,我们实例化Flask-Migrate提供的Migrate类,进行初始化操作:

from flask import Flask, render_template, flash, url_for, redirect
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate app = Flask(__name__)
db = SQLAlchemy(app)
migrate = Migrate(app, db) # 在db对象创建后调用
 

实例化Migrate类时,除了传入程序app,还需要传入实例化Flask-SQLAlchemy提供的SQLAlchemy类创建的db对象作为第二个参数。

1、创建迁移环境--flask db init

在开始迁移数据之前,需要先使用下面的命令创建一个迁移环境:

(Lenovo-ezd1lI9Y) D:\flask\FLASK_PRACTICE\DataBase>flask db init
Creating directory D:\flask\FLASK_PRACTICE\DataBase\migrations ... done
Creating directory D:\flask\FLASK_PRACTICE\DataBase\migrations\versions ... done
Generating D:\flask\FLASK_PRACTICE\DataBase\migrations\alembic.ini ... done
Generating D:\flask\FLASK_PRACTICE\DataBase\migrations\env.py ... done
Generating D:\flask\FLASK_PRACTICE\DataBase\migrations\env.pyc ... done
Generating D:\flask\FLASK_PRACTICE\DataBase\migrations\README ... done
Generating D:\flask\FLASK_PRACTICE\DataBase\migrations\script.py.mako ... done
Please edit configuration/connection/logging settings in 'D:\\flask\\FLASK_PRACTICE\\DataBase\\migrations\\alembic.ini' before proceeding.

Flask-Migrate提供了一个命令集,使用db作为命令集名称,它提供的命令都以flask db开头。你可以在命令行中输入flask—help查看所有可用的命令和说明。

(Lenovo-ezd1lI9Y) D:\flask\FLASK_PRACTICE\DataBase>flask db --help
Usage: flask db [OPTIONS] COMMAND [ARGS]... Perform database migrations. Options:
--help Show this message and exit. Commands:
branches Show current branch points
current Display the current revision for each database.
downgrade Revert to a previous version
edit Edit a revision file
heads Show current available heads in the script directory
history List changeset scripts in chronological order.
init Creates a new migration repository.
merge Merge two revisions together, creating a new revision file
migrate Autogenerate a new revision file (Alias for 'revision...
revision Create a new revision file.
show Show the revision denoted by the given symbol.
stamp 'stamp' the revision table with the given revision; don't run...
upgrade Upgrade to a later version

迁移环境只需要创建一次。这会在你的项目根目录下创建一个migrations文件夹其中包含了自动生成的配置文件和迁移版本文件夹。

2、生成迁移脚本--flask db migrate -m "add note timestamp"

使用migrate子命令可以自动生成迁移脚本:

(Lenovo-ezd1lI9Y) D:\flask\FLASK_PRACTICE\DataBase>flask db migrate -m "add note timestamp"
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.autogenerate.compare] Detected removed table u'draft'
INFO [alembic.autogenerate.compare] Detected removed table u'post'
INFO [alembic.autogenerate.compare] Detected removed table u'comment'
Generating D:\flask\FLASK_PRACTICE\DataBase\migrations\versions\cdd9d12762fc_add_note_timestamp.py ... done

这条命令可以简单理解为在flask里对数据库(db)进行迁移(migrate)。-m选项用来添加迁移备注信息。从上面的输出信息我们可以看到,Alembic检测出了模型变化:表note新加了一个timestamp列,并且相应生成了一个迁移脚本cdd9d12762fc_add_note_timestamp.py:

"""add note timestamp

Revision ID: 7f3dae8cae4d
Revises:
Create Date: 2019-04-01 21:56:32.469000 """
from alembic import op
import sqlalchemy as sa # revision identifiers, used by Alembic.
revision = '7f3dae8cae4d'
down_revision = None
branch_labels = None
depends_on = None def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('draft')
op.drop_table('post')
op.drop_table('comment')
op.add_column('note', sa.Column('timeStamp', sa.String(length=70), nullable=True))
op.create_unique_constraint(None, 'note', ['timeStamp'])
# ### end Alembic commands ### def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'note', type_='unique')
op.drop_column('note', 'timeStamp')
op.create_table('comment',
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('body', sa.TEXT(), nullable=True),
sa.Column('post_id', sa.INTEGER(), nullable=True),
sa.ForeignKeyConstraint(['post_id'], [u'post.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('post',
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('title', sa.VARCHAR(length=50), nullable=True),
sa.Column('body', sa.TEXT(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_table('draft',
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('body', sa.TEXT(), nullable=True),
sa.Column('edit_time', sa.INTEGER(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###
 

从上面的代码可以看出,迁移脚本主要包含了两个函数:upgrate()函数用来将改动应用到数据库,函数中包含了向表中添加timestamp字段的命令,而downgrade()函数用来撤消改动,包含了删除timestamp字段的命令。

就像这两个函数中的注释所说的,迁移命令是有Alembic自动生成的,其中可能包含错误,所以有必要在生成后检查一下。

因为每一次迁移都会生成新的迁移脚本,而且Alemic为每一次迁移都生成了修订版本(revision)ID,所以数据库可以恢复到修改历史中的任一点。正因如此,迁移环境中的文件也要纳入版本控制。

有些复杂的错误无法实现自动迁移,这时可以使用revision命令手动创建迁移脚本。这同样会生成一个迁移脚本,不过脚本中的upgrade()和downgrade()函数都是空的。你需要使用Alembic提供的Operations对象指令在这两个函数中实现具体操作,具体可以访问Alembic官方文档查看。

3、更新数据库--flask db upgrade

生成了迁移脚本后,使用upgrade子命令即可更新数据库:

(Lenovo-ezd1lI9Y) D:\flask\FLASK_PRACTICE\DataBase>flask db upgrade
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> 7f3dae8cae4d, add note timestamp
ERROR [root] Error: No support for ALTER of constraints in SQLite dialect

如果还没有创建数据库和表,这个命令会自动创建,如果已经创建,则会在不损坏数据的前提下执行更新。

从客户端可以看到note表新增加了一个timestamp字段

如果你想回滚迁移,那么可以使用downgrade命令(降级),它会撤销最后一次迁移在数据库中的改动,这在开发时非常有用。比如,当执行upgrade命令后发现某些地方出错了,这时就可以执行flask db downgrade命令进行回滚,删除对应的迁移脚本,重新生成迁移脚本后再进行更新(upgrade)。

SQLite迁移问题:flask db downgrade 报错
(Lenovo-ezd1lI9Y) D:\flask\FLASK_PRACTICE\DataBase>flask db downgrade 5e87b4da6187
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
ERROR [root] Error: Destination 5e87b4da6187 is not a valid downgrade target from current head(s)

是因为sqlite不支持alter机制的原因

开发时是否需要迁移?

在生产环境下,当对数据库结构进行修改后,进行数据库迁移是必要的。因为你不想损坏任何数据,在生成自动迁移脚本之后,执行更新之前,对迁移脚本进行检查,甚至是使用备份的数据库进行迁移测试,都是有必要的。

在开发环境中,你可以按需要选择是否进行数据库迁移,对于大多数程序来说,可以在开发时使用虚拟数据生成工具来生成虚拟数据,从而避免手动创建记录进行测试,这样每次更改表结构时,可以直接清楚后重新生成,然后生成测试数据,这要比执行一次迁移简单的多(后续会学到通过一个命令完成所有工作),除非生成虚拟数据耗费的时间过长。

另外,在本地本地开发时通常使用SQLite作为数据库引擎。SQLite不支持ALTER语句,而这正是迁移工具依赖的工作机制,也就是说,当SQLite数据库的字段删除或修改后,我们没法直接使用迁移工具进行更新,你需要手动添加迁移代码进行迁移。在开发中,修改和删除列是很常见的行为,手动操作迁移会花费太多时间。

对于SQLite,迁移工具一般使用”move and copy”的工作流(创建新表、迁移数据、删除旧表)达到类似的效果。

如果希望让生产环境的部署更搞笑,则应该尽可能让开发环境和生产环境保持一致。这时应该考虑直接在本地使用MySQL或其他的DBMS,然后设置迁移环境。

flask 使用Flask-Migrate迁移数据库(创建迁移环境、生成迁移脚本、更新数据库)的更多相关文章

  1. PD模型创建完获取生成表脚本

    1.双击表名,弹出属性对话框-->General----> Owner 表名前缀,如XX.SYS_TABLE  最好去掉 2.Preview 复制里面的脚本到数据库执行下即可

  2. mysql快速生成truncate脚本清空数据库表记录

    语句格式: select CONCAT('truncate TABLE ',table_schema,'.',TABLE_NAME, ';') from INFORMATION_SCHEMA.TABL ...

  3. flask中如何生成迁移文件

    在flask网站开发中,如果直接对数据库进行修改的话,风险比较高,最好的是由迁移文件生成,这样确保了数据的误操作. 在Flask中可以使用Flask-Migrate扩展,来实现数据迁移.并且集成到Fl ...

  4. MSSQL为单独数据库创建登录账户

    如果要为一个数据库创建一个独立的账号需要这个数据库为包含数据库 当前(非包含)的数据库所面临的问题在描述什么是包含数据库之前,先了解一下为什么会出现包含数据库.当前的数据库有一些问题,如下:1.在数据 ...

  5. 创建human用户登录数据库创建表

    根据人力资源管理系统中表的设计,创建human用户登录数据库创建 准备阶段 把运行脚本复制到D:\app\Administrator\product\11.2.0\dbhome_1\demo\sche ...

  6. LINQ to SQL更新数据库操作(转载)

    使用LINQ to SQL建模Northwind数据库 在这之前一起学过LINQ to SQL设计器的使用,下面就使用如下的数据模型: 当使用LINQ to SQL设计器设计以上定义的五个类(Prod ...

  7. 基于数据库的代码自动生成工具,生成JavaBean、生成数据库文档、生成前后端代码等(v6.0.0版)

    TableGo v6.0.0 版震撼发布,此次版本更新如下: 1.UI界面大改版,组件大调整,提升界面功能的可扩展性. 2.新增BeautyEye主题,界面更加清新美观,也可以通过配置切换到原生Jav ...

  8. mac安装mysql数据库及配置环境变量

    mac安装mysql数据库及配置环境变量 mac安装mysql数据库及配置环境变量 原文文链接:https://blog.csdn.net/qq_36004521/article/details/80 ...

  9. Laravel5.5 数据库迁移:创建表与修改表

    数据库迁移是数据库的版本管理,要使用数据库迁移,需要在.env文件中连接好数据库(不多说).laravel本身已经存在user表和password_resets表的迁移了,因此,执行 php arti ...

随机推荐

  1. 自动化测试工具Katalon简单使用

    前一段时间接触了下Katalon,当时只是简单用了下,今天看到Katalon给发邮件,发现都忘记了,因此重新学习并记录下来 Katalon是在Selemium相同的内核上构建起来的一个自动化测试工具 ...

  2. java生成zip压缩文件,解压缩文件

    1.生成zip public static void main(String[] args) { try { // testZip("c:\\temp.txt", "c: ...

  3. 搭建Pypi转发服务

    有时候有些正式环境的机器,不能访问外网,就只能在能访问外网的机器上搭建一个转发服务. 一.安装包 pip install flask_pypi_proxy flask_pypi_proxy 二.启动 ...

  4. 使用Pip在离线环境安装Python依赖库

    一.安装多个包 1.有网的服务器 1.生成requirement.txt文件 pip freeze >/tmp/wheel_pip/requirements.txt 这个命令会把当前环境下面的p ...

  5. 【物联网】国内几大云计算厂商的物联网IOT解决方案-阿里云、腾讯、百度、华为、青云(转)

    一.前言随着万物互联时代的来临,IOT逐渐成为各大云计算厂商重点发力的方向,作为平台厂商,提供的是包含接入.存储.管理.计算.展示等多个方面的综合能力,我这里就根据它们各自的特点和能力,简单介绍下它们 ...

  6. Excel条件格式

    任务需求,将Excel中年龄为90后出生的人员筛选出来,并将重复的人员数据删除. 一.Excel去重 选中表格数据->数据->删除重复值 此时弹出对话框,选择去重列. 点击确定即可. 二. ...

  7. 18 南京 D

    裸的最小球覆盖. 坐标范围大一些所以我们把初始的温度也设置的大一些. #include <bits/stdc++.h> using namespace std; typedef long ...

  8. centos7 与 archlinux用户 安装 python3模块 pytaglib

    对于 centos7用户: yum group install "Development Tools" yum install taglib-devel yum install p ...

  9. ArcGIS AddIN 10.3项目与10.1项目的相互转换

    1. .sln修改 用记事本打开.sln文件,在最上面将10的I昂么修改为12的项目 将下图 修改为下图 反之亦然 2. .csproj项目修改 用记事本打开.csproj文件, vs 2010文件如 ...

  10. html table 固定表头和列

    /**************************************************************** jQuery 插件. 功能: 固定表格标题行或列头 Version: ...