Flask-Migrate的使用和常见"坑"的解决办法

摘要:
解决方案:已安装指定的版本。测试后,烧瓶==1.1.2烧瓶-格栅==2.7.0不会造成问题。在安装了flask migrate之后,为了更好地使用它,我们还需要安装另一个非常实用的插件,flask脚本,这是一个用于项目管理的插件。您可以自定义命令来管理我们的项目。因此,请尝试手动检查迁移生成的脚本。
1.Flask-Migrate的使用

flask-migrate相关配置:

1 from Application import app
2 from common.models.model import db
3 from flask_migrate import Migrate, MigrateCommand
4 
5 migrate = Migrate(app, db, render_as_batch=True, compare_type=True, compare_server_default=True)
6 manager.add_command('db', MigrateCommand)
7 manager.add_command('runserver', Server(host='0.0.0.0'))
8 if __name__ == '__main__':
9 manager.run()
flask-migrate相关的命令:
  • python manage.py db init:初始化一个迁移脚本的环境,只需要执行一次。
  • python manage.py db migrate:将模型生成迁移文件,只要模型更改了,就需要执行一遍这个命令。
  • python manage.py db upgrade:将迁移文件真正的映射到数据库中。每次运行了migrate命令后,就记得要运行这个命令。
2. 常见"坑"的解决办法

第一坑:安装最新版本的flask-migrate插件

首先安装flask-migrate,如果直接pip install flask-migrate安装,默认是安装的是最新版本,这时候你会发现,最新版本和flask的版本会有冲突,导入MigrateCommand时报错。

解决办法

指定版本安装 ,经过测试:Flask==1.1.2  flask-migrate==2.7.0不会出现问题。

    安装完flask-migrate后,为了更好的使用它,我们还得安装另一个很实用的插件flask-script,这是一个项目管理类的插件,可以自定义命令去管理我们的项目。同样的该插件的最新版本,也会和高版本的flask产生冲突,经过测试Flask==1.1.2不会出现问题。

所以说,如果要使用以上两个插件,Flask版本不能太高,否则会出现兼容问题。

  

第二坑:当使用sqlite时的alter

这次坑的是sqlite,主要是sqlite自己太坑。它不支持drop列,不支持完整的数据库alter语句功能等等。当使用sqlite做migrate和upgrade以及downgrade时,模型有字段的减少或者约束的减少,会报错:

sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) near "DROP": syntax error [SQL: ALTER TABLE account DROP COLUMN name]

解决方法:

初始化Migrate对象时可以设置其提交类型为批处理 migrate = Migrate(db=db, render_as_batch=True)

    以批处理的方式做表结构修改sqlite是支持的,但是批处理本身有安全性的问题。批处理提升了效率,但是丧失了原子性,其中某些sql语句出错我们并不能直接感知到。所以尽量对migrate生成的脚本进行人工检查吧,不怕一万就怕万一。

  

第三坑:字段长度等属性的修改

FlaskMigrate默认对字段属性的变动是不做检查的。所以当发现256长的A字段的不足以支撑功能,我们需要把它变成1000,修改代码后做migrate会发现提示No changes in schema detected.

解决方法:

上面提到的alembic的源码的EnvironmentContext类内的configure方法里有个sqlalchemy_module_prefix参数旁边还有一些其他的小参数,这次没有坑爹,比较给力,还是贴一下源码吧:

Flask-Migrate的使用和常见"坑"的解决办法第1张Flask-Migrate的使用和常见"坑"的解决办法第2张
 1 def configure(
 2         self,
 3         connection=None,
 4         url=None,
 5         dialect_name=None,
 6         dialect_opts=None,
 7         transactional_ddl=None,
 8         transaction_per_migration=False,
 9         output_buffer=None,
10         starting_rev=None,
11         tag=None,
12         template_args=None,
13         render_as_batch=False,
14         target_metadata=None,
15         include_name=None,
16         include_object=None,
17         include_schemas=False,
18         process_revision_directives=None,
19         compare_type=False,
20         compare_server_default=False,
21         render_item=None,
22         literal_binds=False,
23         upgrade_token="upgrades",
24         downgrade_token="downgrades",
25         alembic_module_prefix="op.",
26         sqlalchemy_module_prefix="sa.",
27         user_module_prefix=None,
28         on_version_apply=None,
29         **kw
30     ):
View Code

这里有一个熟悉的面孔,没错!二号坑里的render_as_batch参数也在这里。同时,还有一个叫做compare_type的参数,默认是False,该参数用于标注是否比较字段属性变化。所以,同二号坑,在初始化Migrate对象的时候加入该参数,如下:

Migrate(db=db, render_as_batch=True, compare_type=True)

 

第四坑:default默认约束的生成

     sqlalchemy的默认值设置有两种方式,第一种是直接的在Column中设置default,这种方式并不在数据库生成默认值约束,是依靠sqlalchemy自身的功能在生成数据的时候生成默认值。另一种是server_default,这种方式是直接在数据库内生成默认值约束。使用较为麻烦,因为server_default参数只接受str或者unicode这种类型,比如Integer字段也需要设置为字符串,时间戳则需要自己转化,较为麻烦。所以,想要在数据迁移时生成数据库的约束,需要使用server_default而不是default。此外,在三号坑内的源码里,也能看见一个熟脸,就是compare_server_default,默认值是False。

解决方法:

1.保证model内所有有默认值的字段的default以server_default形式设置。 

2.初始化Migrate对象时做配置:migrate = Migrate(db=db, render_as_batch=True, compare_type=True, compare_server_default=True)

 

除了以上4个比较常见的坑外,其实还有很多,不过我在学习过程中遇到暂时就只有这四个,后续如果遇到会补充。

参考博客:https://blog.csdn.net/c_s_y/article/details/90769675

 

免责声明:文章转载自《Flask-Migrate的使用和常见"坑"的解决办法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇关于centos启动报错:Failed to start Crash recovery kernel arming的解决方案java 程序执行原理下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

【FLASK】上传文件

## 后端:importos from flask importrequest, jsonify from werkzeug.utils importsecure_filename from flask importFlask, request importhashlib importtime app = Flask(__name__) @app...

java使用jdbc对sqlite 添加、删除、修改的操作

package com.jb.jubmis.Dao.DaoImpl; import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import...

Android provider中使用sqlite内存数据库

      sqlite是支持内存数据库的,在Android中,我们可以通过provider实现内存数据库操作。内存数据库的优点,访问速度快,但在连接关闭后,数据库自动消失(在android中的表现是,provider所在进程死了,内存库就没了)。应用场景,对于一次会话产生的临时数据或者密码等安全数据,这些数据仅想在应用运行期间有效,可以考虑用内存数据库。...

Flask入门之SQLAlchemy数据库连接操作(第15讲)

一、库安装 Flask-SQLAlchemy 2 SQLAlchemy 1.0.8 二、进入venv 三、切换到项目Sample 文件夹,进入manager.py 的shell python manager.py shell 四、创建data.sqlite数据库 from app import db from app import mod...

危化品速查APP--Android Project

开发环境 Android studio 2.3.1 功能描述 集成多种查询方式,查看本地数据库中危险化学品的信息; 按照中文拼音和英文首字母,对化学品进行查询; 按照UN号或者CAS号查询相应的化学品; 按照化学品特性描述的关键词检索化学品; 查看产品手册以及使用说明文档; Github 地址 git@github.com:guoyaohua/Chem...

用systemtap分析磁盘写入操作

用systemtap分析磁盘写入操作转载时请注明出处和作者联系方式作者联系方式:李先静 <xianjimli at hotmail dot com>这几天发现有好几块broncho开发板的FLASH坏了,broncho使用的SLC,现在的SLC写入寿命至少在10W次以上,尽管现在的测试要比正常使用高得多,也没有可能在不到一个月就坏了啊。不过最近...