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比较2个xml内容的方法
May 11 Python
Python查询IP地址归属完整代码
Jun 21 Python
Python实现希尔排序算法的原理与用法实例分析
Nov 23 Python
浅谈Python使用Bottle来提供一个简单的web服务
Dec 27 Python
python 3.6.4 安装配置方法图文教程
Sep 18 Python
python实现顺序表的简单代码
Sep 28 Python
对python中的six.moves模块的下载函数urlretrieve详解
Dec 19 Python
对Python生成汉字字库文字,以及转换为文字图片的实例详解
Jan 29 Python
用Python解决x的n次方问题
Feb 08 Python
pyqt5数据库使用详细教程(打包解决方案)
Mar 25 Python
python实现将字符串中的数字提取出来然后求和
Apr 02 Python
基于python实现监听Rabbitmq系统日志代码示例
Nov 28 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
preg_match_all使用心得分享
2014/01/31 PHP
php获取系统变量方法小结
2015/05/29 PHP
Ubuntu下安装PHP的mongodb扩展操作命令
2015/07/04 PHP
PHP设计模式之模板方法模式定义与用法详解
2018/04/02 PHP
php解压缩zip和rar压缩包文件的方法
2019/07/10 PHP
php项目中类的自动加载实例讲解
2019/09/12 PHP
laravel withCount 统计关联数量的方法
2019/10/10 PHP
javascript replace()正则替换实现代码
2010/02/26 Javascript
Javascript 面试题随笔
2011/03/31 Javascript
jquery插件制作 提示框插件实现代码
2012/08/17 Javascript
js获取checkbox复选框选中的选项实例
2014/08/24 Javascript
jQuery中insertAfter()方法用法实例
2015/01/08 Javascript
jquery实现简单的全选和反选功能
2016/01/02 Javascript
用NodeJS实现批量查询地理位置的经纬度接口
2016/08/16 NodeJs
canvas滤镜效果实现代码
2017/02/06 Javascript
jQuery Plupload上传插件的使用
2017/04/19 jQuery
在JS中如何把毫秒转换成规定的日期时间格式实例
2017/05/11 Javascript
详解React之父子组件传递和其它一些要点
2018/06/25 Javascript
Bootstarp在pycharm中的安装及简单的使用方法
2019/04/19 Javascript
JS中的算法与数据结构之常见排序(Sort)算法详解
2019/08/16 Javascript
Vue管理系统前端之组件拆分封装详解
2020/08/23 Javascript
vue组件中实现嵌套子组件案例
2020/08/31 Javascript
在python中以相同顺序shuffle两个list的方法
2018/12/13 Python
python利用dlib获取人脸的68个landmark
2019/11/27 Python
python如何运行js语句
2020/09/09 Python
荷兰皇家航空公司官方网站:KLM Royal Dutch Airlines
2017/12/07 全球购物
餐饮业会计岗位职责
2013/12/19 职场文书
2015届大学生就业推荐表自我评价
2014/09/27 职场文书
常务副县长“四风”个人对照检查材料思想汇报
2014/10/02 职场文书
幼儿园2014年度工作总结
2014/11/10 职场文书
会计出纳岗位职责
2015/03/31 职场文书
迁徙的鸟观后感
2015/06/09 职场文书
保外就医申请书范文
2015/08/06 职场文书
CSS中em的正确打开方式详解
2021/04/08 HTML / CSS
Redis 持久化 RDB 与 AOF的执行过程
2021/11/07 Redis
Django框架中模型的用法
2022/06/10 Python