新版Flask-SQLAlchemy和Flask-Migrate的踩坑指南(2022.07)

一、版本环境

看了很多文章,没有写清楚环境的版本,导致解决方案根本对不上号,所以我先把本人使用的主要模块版本列出来

Flask==2.1.3
Flask-Migrate==3.1.0
Flask-Script==2.0.6
Flask-SQLAlchemy==2.5.1

本人开发环境为Windows + VSCode

二、遇到的问题

一开始,我按照网上的大部分教程所说,使用flask_script来执行数据迁移命令,主要代码如下:

from flask_migrate import Migrate,MigrateCommand
from flask_script import Manager

manager = Manager(app)
# flask-script集成的数据库操作
manager.add_command('db', MigrateCommand)

结果遇到一些错误,下面一一说明。

1.No module named 'flask._compat'

完整提示:

F:\Python\flask\flask_orm_admin>python3 main.py db init
Traceback (most recent call last):
  File "main.py", line 6, in <module>
    from flask_script import Manager
  File "D:\Python3\lib\site-packages\flask_script\__init__.py", line 15, in <module>
    from flask._compat import text_type
ModuleNotFoundError: No module named 'flask._compat'

然后搜解决办法,发现很多人给的解决办法就是降低Flask的版本,改用1.x的版本

我了个去,这叫什么解决方案?以后还都不用新版本了?后来找到一个靠谱的解决办法:

修改flask_script 文件就可以
It happened because the python searched on Flask._compat directory and It isn't there, so I changed like on below : (on flask_script/__init__.py)

Where:

from ._compat import text_type on original flask-script file

to :

from flask_script._compat import text_type

试了一下,果然不再报这个错了,踩过了第一个坑。

然后继续按网上教程操作,又遇到一个坑。。

2.cannot import name 'MigrateCommand' from 'flask_migrate'

完整提示“:

F:\Python\flask\flask_orm_admin>python3 main.py db init
Traceback (most recent call last):
  File "main.py", line 5, in <module>
    from flask_migrate import Migrate,MigrateCommand
ImportError: cannot import name 'MigrateCommand' from 'flask_migrate' (D:\Python3\lib\site-packages\flask_migrate\__init__.py)

其实我还没运行的时候,我的VSCode已经提示我找不到MigrateCommand了

解决办法:

网上一搜,给出的解决方案又是降级!真是服了!继续找,终于找到一篇有用的 https://www.jianshu.com/p/11ce08e078aa

发现flask_migrate已经不再支持flask_script了,所以没有了MigrateCommand

因此,在我的代码中去掉了flask_script相关的内容,对代码进行了调整。

三、数据迁移

准备就绪之后,开始数据迁移工作

由于不再使用flask_script,而是使用flask db命令,所以跟网上的教程有一些变化

执行flask db init,会报错:

F:\Python\flask\flask_orm_admin\server>flask db init
Usage: flask db init [OPTIONS]
Try 'flask db init --help' for help.

Error: Could not locate a Flask application. You did not provide the "FLASK_APP" environment variable, and a "wsgi.py" or "app.py" module wa
s not found in the current directory.

就是说,flask需要找到一个Flask的实例app,FLASK_APP通常指定为主程序

set FLASK_APP=main.py

然后再执行flask db init

此时可能会出现导入模块错误,比如找不到连接数据库的ext.py,考虑到应该是因为直接执行flask命令时可能找不到本项目的路径,需要在main.py头部加上一些代码:

import sys,os
curdir = os.path.dirname(__file__)
sys.path.append(curdir)
sys.path.append(curdir + "..\\")

这样就可以解决找不到模块的问题了,继续执行

F:\Python\flask\flask_orm_admin\server>flask db init
Creating directory F:\Python\flask\flask_orm_admin\server\migrations\versions ...  done
Generating F:\Python\flask\flask_orm_admin\server\migrations\alembic.ini ...  done
Generating F:\Python\flask\flask_orm_admin\server\migrations\env.py ...  done
Generating F:\Python\flask\flask_orm_admin\server\migrations\README ...  done
Generating F:\Python\flask\flask_orm_admin\server\migrations\script.py.mako ...  done
Please edit configuration/connection/logging settings in 'F:\\Python\\flask\\flask_orm_admin\\server\\migrations\\alembic.ini' before proceeding.

这个提示信息看起来是正常的,继续执行flask db migrate,-m参数可以为本次迁移添加一个消息,就像git的提交消息一样,后续一旦有问题还可以回滚

F:\Python\flask\flask_orm_admin\server>flask db migrate -m "add t_user"
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 't_user'
Generating F:\Python\flask\flask_orm_admin\server\migrations\versions\5c8e40bf5e34_add_t_user.py ...  done

提示信息正常,检测到新表t_user,并生成了一个5c8e40bf5e34_add_t_user文件,有兴趣的读者可以根据路径找到这个文件,看看里面的内容

接下来执行flask db upgrade

F:\Python\flask\flask_orm_admin\server>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  -> 5c8e40bf5e34, add t_user

没有报错,应该是正常的。此时可以打开数据库检查一下,会发现t_user表已经建立好了

接下来再添加一个t_admin表,建立相应的Model,在main.py中添加导入,然后重复migrate和upgrade的过程

F:\Python\flask\flask_orm_admin\server>flask db migrate -m "add t_admin"
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 't_admin'
Generating F:\Python\flask\flask_orm_admin\server\migrations\versions\d91575857413_add_t_admin.py ...  done

F:\Python\flask\flask_orm_admin\server>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 5c8e40bf5e34 -> d91575857413, add t_admin

检查了一下也是正常的。

其它的一些情况,我把注释都写在源码里了,自行查看即可

四、添加数据

使用著名的Faker库,来向user表添加一些数据。

import sys
sys.path.append("..")

from faker import Faker
from main import create_app
#导入模型
from user.models import User

fake = Faker(locale="zh-CN")
app = create_app()
db = app.config["db"]

#添加10个用户
def addFakeUser():
    try:
        with app.app_context():
            for _ in range(10):
                user = User(username=fake.name())
                user.password = fake.random_number(7)
                user.email = fake.email()
                user.phone = fake.phone_number()
                user.money = fake.random_int()
                user.userip = fake.ipv4()
                print(user.username,user.email)
                #添加并提交
                db.session.add(user)
                db.session.commit()
    except Exception as e:
        print("数据库操作失败")
        raise
    else:
        return True

addFakeUser()

然后访问接口http://127.0.0.1:5000/user/list,就可以看到数据了!

相关代码已放在 https://gitee.com/achillis/flask_demo ,欢迎访问

posted @ 2022-07-22 23:24  黑月教主  阅读(5352)  评论(0编辑  收藏  举报