Python的Flask框架中使用Flask-Migrate扩展迁移数据库的教程


Posted in Python onJune 14, 2016

我们在升级系统的时候,经常碰到需要更新服务器端数据结构等操作,之前的方式是通过手工编写alter sql脚本处理,经常会发现遗漏,导致程序发布到服务器上后无法正常使用。

现在我们可以使用Flask-Migrate插件来解决之,Flask-Migrate插件是基于Alembic,Alembic是由大名鼎鼎的SQLAlchemy作者开发数据迁移工具。

具体操作如下:

1. 安装Flask-Migrate插件

$ pip install Flask-Migrate
2. 修改Flask App部分的代码,以增加Migrate相关的Command
db = SQLAlchemy(app)
migrate = Migrate(app, db)

manager = Manager(app)
manager.add_command('db', MigrateCommand)

3. 初始化

$ python app.py db init

使用Flask-Migrate迁移数据库
随着开发进度不断向前,你会发现你的数据库模型需要更改,而当这种情况发生时需要更新数据库。

Flask-SQLAlchemy只有当数据库表不存在了才从模型创建它们,所以更新表的唯一途径就是销毁旧的表,当然这将导致所有数据库中的数据丢失。

有个更好的解决方案就是使用数据库迁移框架。和源码版本控制工具跟踪更改源码文件一样,数据库迁移框架跟踪更改数据库模型,然后将增量变化应用到数据库中。

SQLAlchemy的主要开发人员写了一个Alembic迁移框架,但我们不直接使用Alembic,Flask应用可以使用Flask-Migrate扩展,一个集成了Flask-Script来提供所有操作命令的轻量级Alembic包。

4. 创建迁移仓库

首先,Flask-Migrate必须已经安装到虚拟环境中:

(venv) $ pip install flask-migrate

下面展示扩展如何初始化:

from flask.ext.migrate import Migrate, MigrateCommand 

# ...

migrate = Migrate(app, db)
manager.add_command('db', MigrateCommand)

为了可以使用数据库迁移命令,Flask-Migrate提供MigrateCommand类来连接Flask-Script的manager对象。在这个示例中使用db来连接到命令。

在数据库迁移可以维护之前,必须通过init子命令来创建一个迁移库:

(venv) $ python hello.py db init
Creating directory /home/flask/flasky/migrations...done
 Creating directory /home/flask/flasky/migrations/versions...done
 Generating /home/flask/flasky/migrations/alembic.ini...done
 Generating /home/flask/flasky/migrations/env.py...done
 Generating /home/flask/flasky/migrations/env.pyc...done
 Generating /home/flask/flasky/migrations/README...done
 Generating /home/flask/flasky/migrations/script.py.mako...done
 Please edit configuration/connection/logging settings in
 '/home/flask/flasky/migrations/alembic.ini' before proceeding.

这个命令创建一个migrations文件夹,里面存放了所有迁移脚本。

建议:如果你有克隆在GitHub上的应用程序,你现在可以运行git checkout 5c来切换到这个版本的应用程序。

5. 创建迁移脚本

在Alembic,数据库迁移工作由迁移脚本完成。这个脚本有两个函数,分别叫做upgrade()和downgrade()。upgrade()函数实施数据库更改,是迁移的一部分,downgrade()函数则删除它们。通过添加和删除数据库变化的能力,Alembic可以重新配置数据库从历史记录中的任何时间点。

Alembic迁移可以分别使用revision和migrate命令手动或自动创建。手动迁移通过由开发人员使用Alembic的Operations对象指令实现的空upgrade()和downgrade()函数创建迁移框架脚本。另一方面,自动迁移通过寻找模型定义和数据库当前状态间的不同为upgrade()和downgrade()生成代码。

警告:自动迁移并不总是准确的,可以忽略一些细节。所以应该经常审查一下自动生成的迁移脚本。
migrate子命令创建自动迁移脚本:

(venv) $ python hello.py db migrate -m "initial migration"
INFO [alembic.migration] Context impl SQLiteImpl.
INFO [alembic.migration] Will assume non-transactional DDL.
INFO [alembic.autogenerate] Detected added table 'roles'
INFO [alembic.autogenerate] Detected added table 'users'
INFO [alembic.autogenerate.compare] Detected added index
'ix_users_username' on '['username']'
 Generating /home/flask/flasky/migrations/versions/1bc
 594146bb5_initial_migration.py...done

建议:如果你有克隆在GitHub上的应用程序,你现在可以运行git checkout 5c来切换到这个版本的应用程序。注意,你不需要为这个应用生成migrations,所有的迁移脚本都包含在版本库中。
6. 更新数据库

一旦迁移脚本被审查且接受,就可以使用db upgrade命令更新到数据库中:

(venv) $ python hello.py db upgrade
INFO [alembic.migration] Context impl SQLiteImpl.
INFO [alembic.migration] Will assume non-transactional DDL.
INFO [alembic.migration] Running upgrade None -> 1bc594146bb5, initial migration

第一次迁移实际上相当于调用db.create_all(),但在后续迁移中,upgrade命令对表实施更新操作但不影响表中的内容。

Python 相关文章推荐
Python安装第三方库的3种方法
Jun 21 Python
图文讲解选择排序算法的原理及在Python中的实现
May 04 Python
Python找出list中最常出现元素的方法
Jun 14 Python
Python简单实现安全开关文件的两种方式
Sep 19 Python
对python多线程中Lock()与RLock()锁详解
Jan 11 Python
Ubuntu18.04中Python2.7与Python3.6环境切换
Jun 14 Python
python切片(获取一个子列表(数组))详解
Aug 09 Python
Python算法的时间复杂度和空间复杂度(实例解析)
Nov 19 Python
wxpython多线程防假死与线程间传递消息实例详解
Dec 13 Python
利用jupyter网页版本进行python函数查询方式
Apr 14 Python
Java多线程实现四种方式原理详解
Jun 02 Python
利用Python中的Xpath实现一个在线汇率转换器
Sep 09 Python
Python的Flask框架中使用Flask-SQLAlchemy管理数据库的教程
Jun 14 #Python
全面了解Python的getattr(),setattr(),delattr(),hasattr()
Jun 14 #Python
浅谈python中的getattr函数 hasattr函数
Jun 14 #Python
深入解析Python中的线程同步方法
Jun 14 #Python
详解Python中的Descriptor描述符类
Jun 14 #Python
浅析Python中的getattr(),setattr(),delattr(),hasattr()
Jun 14 #Python
Python中getattr函数和hasattr函数作用详解
Jun 14 #Python
You might like
如何使用PHP获取指定日期所在月的开始日期与结束日期
2013/08/01 PHP
php中cookie的使用方法
2014/03/29 PHP
Laravel 5 框架入门(二)构建 Pages 的管理功能
2015/04/09 PHP
Prototype中dom对象方法汇总
2008/09/17 Javascript
javascript得到XML某节点的子节点个数的脚本
2008/10/11 Javascript
jQuery+jRange实现滑动选取数值范围特效
2015/03/14 Javascript
JavaScript对表格或元素按文本,数字或日期排序的方法
2015/05/26 Javascript
基于nodejs+express(4.x+)实现文件上传功能
2015/11/23 NodeJs
微信小程序 chooseImage选择图片或者拍照
2017/04/07 Javascript
vue使用Element组件时v-for循环里的表单项验证方法
2018/06/28 Javascript
原生javascript自定义input[type=radio]效果示例
2019/08/27 Javascript
通过vue写一个瀑布流插件代码实例
2019/09/07 Javascript
vue点击Dashboard不同内容 跳转到同一表格的实例
2020/11/13 Javascript
[01:22:19]EG vs TNC Supermajor小组赛B组败者组第一轮 BO3 第二场 6.2
2018/06/03 DOTA
用Python实现一个简单的多线程TCP服务器的教程
2015/05/05 Python
详解Django中的过滤器
2015/07/16 Python
Python批量更改文件名的实现方法
2017/10/29 Python
Python实现的摇骰子猜大小功能小游戏示例
2017/12/18 Python
Python实现正则表达式匹配任意的邮箱方法
2018/12/20 Python
Python3实现对列表按元组指定列进行排序的方法分析
2018/12/22 Python
python实现狄克斯特拉算法
2019/01/17 Python
Python动态强类型解释型语言原理解析
2020/03/25 Python
python 实现表情识别
2020/11/21 Python
HTML5适合的情人节礼物有纪念日期功能
2021/01/25 HTML / CSS
Timberland澳大利亚官网:全球领先的户外品牌
2019/12/10 全球购物
生产车间实习自我鉴定
2013/09/23 职场文书
药学专业大学生自荐信
2013/09/28 职场文书
科级干部考察材料
2014/02/15 职场文书
岗位职责风险点
2014/03/12 职场文书
销售岗位职责范本
2014/06/12 职场文书
机械设计专业大学生职业生涯规划书范文
2014/09/13 职场文书
电子商务专业求职信范文
2015/03/19 职场文书
《青山不老》教学反思
2016/02/22 职场文书
css3实现的加载动画效果
2021/04/07 HTML / CSS
Nginx四层负载均衡的配置指南
2021/06/11 Servers
SQL SERVER中的流程控制语句
2022/05/25 SQL Server