Flask脚本(flask-script/flask-migrate)、数据库迁移出现的问题
一、flask-script用法
flask官方提供了一个扩展组件flask-script
可以实现在shell
下操作我们的Flask
项目。
安装flask-script
pip install flask-script
1.flask-script简单实现
server.py
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World!' if __name__ == '__main__': app.run()
manage.py
from flask_script import Manager from server import app manager = Manager(app) @manager.command def hello(): print('hello world') if __name__ == '__main__': manager.run()
解读:manage.py
1.从flask_script模块中导入flask_script的核心类Manager
from flask_script import Manager
2.从server.py模块中把app对象导入
from server import app
3.从Manager()类传入app对象实例化出manager对象,manager对象用于后面所有添加命令
manager = Manager(app)
4.利用@manager.command
装饰器添加以被装饰函数的名字命名的一条命令
与被装饰函数的映射
@manager.command # 相当于添加了一条hello命令,可以调用到hello函数 def hello(): print('hello world')
5.manager调用run方法之前定义的命令才会生效
if __name__ == '__main__': manager.run()
在shell中切入到该manage.py的目录中,并且进入虚拟环境。输入命令python manage.py hello
>>python manage.py hello
命令中的hello是@manager.command装饰器装饰的函数名,执行命令后会调用hello函数
2.命令添加方式 (在manage.py文件中写)
第一种(无参命令): 使用manager.command方式添加命令
... @manager.command def demo(): print('无参命令') ...
执行命令:
>>python manage.py demo
第二种(有参命令): 使用manager.option('-简单的命令','--全写的命令',dest='传给函数的参数')添加命令
... @manager.option("-u","--username",dest="username") @manager.option("-p","--password",dest="password") def login(username, password): print("用户名:{} 密码: {}".format(username,password)) ...
执行命令:
>>python manage.py login -u mark -p 123
第三种(子命令):
比如一个功能对应着很多个命令,这个时候就可以用子命令来实现,可以将这些命令的映射单独放到一个文件方便管理。在这个放着很多命令映射的文件中实例化Manager类出一个新的对象,并在manage.py
文件中通过以下命令来添加子命令
manager.add_command("子命令",Manager对象)
db_script.py文件 (命令映射文件)
from flask_script import Manager db_Manager = Manager() @db_Manager.command def init(): print('初始迁移仓库') @db_Manager.command def migrate(): print('生成迁移脚本') @db_Manager.command def upgrade(): print("迁移脚本映射到数据库")
manage.py
from flask_script import Manager from server import app from db_script import db_Manager # 导入子命令文件的Manager类实例化出的对象 manager = Manager(app) manager.add_command("db",db_Manager) # 添加子命令
切入到manage.py所在的目录中,执行以下命令
>> python manage.py db init
>> python manage.py db migrate
>> python manage.py db upgrade
二、使用Flask-Migrate迁移数据库
pip install flask-migrate
为了导出数据库迁移命令,Flask-Migrate提供了一个MigrateCommand类,可附加到Flask-Script的manager对象上。在这个例子中,MigrateCommand类使用db命令附加
我们的Flask_Migrate的操作是在shell下完成的,所以要基于Flask-script,Flask-Migrate提供了一个MigrateCommand类,需要附加到Flask-Script的manager对象上,完成命令的创建,
并且Flask_Migrate同时体统了Migrate类,需要加载核心对象app和数据库对象db。完成迁移工具的配置。
1.配置Flask_Migrate
manage.py
from flask_script import Manager from flask_migrate import Migrate,MigrateCommand from exts import db from server import app manager = Manager(app) Migrate(app,db) manager.add_command('db',MigrateCommand)
解读:manage.py
1.首先从flask_migrate中导入Migrate,MigrateCommand
from flask_migrate import Migrate,MigrateCommand
2.Migrate加载app对象和db对象获取数据库的配置信息以及模型表信息
Migrate(app,db)
3.把MigrateCommand附加到manager创建迁移数据库的子命令
manager.add_command('db',MigrateCommand) #db是迁移命令的对象,名字可以随便取
2.迁移脚本命令
1.创建迁移仓库
>> python manage.py db init
这个命令会创建migrations文件夹,所有迁移文件都放在里面。这里只是创建了迁移仓库,表还没创建
2.创建迁移脚本
>> python manage.py db migrate -m '注释信息' #注释信息可写可不写
该命令会在数据库创建一张 alembic_version
表,存放着数据库迁移脚本的版本信息,该命令会搜集到需要迁移的模型表信息,写入到脚本中,但是并没有真正的映射到数据库中。
3.更新数据库
>> python manage.py db upgrade
如果对models.py进行修改,需要重新执行
python manage.py db migrate -m "新版本注释" python manage.py db upgrade
三、数据库迁移期间出现的问题
1.执行 python manage.py db init 可以正常生成文件夹migrations
2.运行 python manage.py db migrate 无法生成建表文件,migrations文件夹下的versions为空,同时控制台报一个警告,这个并不是无法生成建表文件的原因
Warning: (1366, "Incorrect string value: '\\xD6\\xD0\\xB9\\xFA\\x B1\\xEA...' for column 'VARIABLE_VALUE' at row 484")
无法生成建表文件是因为:
原来flask-migrate是检测上下文中db.Model的子类来创建表的,所有我们必须让这个app能够知道有这个models文件的存在,所以,在app的文件夹里的__init__文件夹中加上,
因为我们在manage.py中导入app中的文件时,会自动导入__init__.py文件夹,或者在manage.py中导入也行 在__init__.py 或者manage.py 中导入models里面的所有类 from App.models import * 具体导入看自己写的模块路径
这一句,就可以顺利生成建表文件及表结构文件。注意:如果之前有migrate文件夹,需要先将migrate文件夹删除
python manage.py db migrate -m 'data_test'
python manage.py db upgrade