1.说明:
当我们在使用flask框架时,写了一个class类,定义了一个实体,我们一般执行如下命令db.create_all()
映射到数据库库去,这样最开始没问题,但是当你项目上线时,你会发现你想新增一个字段时,你必须把原有的表给删掉db.drop_all()
,再来执行db.create_all()
这样才能更新字段,这样会把表里的数据给删掉,这样做不是一个明智的方式, flask给我们提供了两个插件
flask-migrate // 执行数据表迁移
flask-script //编写脚本执行数据表迁移, 需要与flask-migrate配合使用
flask-migrate文档
flask-script文档
2.使用
pip install flask-migrate==2.7.0
pip install Flask-Script==2.0.6
3.演示:
flask-migrate用法:
import enum
import pymysql
from flask import Flask, url_for, render_template, request, redirect, make_response
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate, MigrateCommand
# from flask_script import Manager
pymysql.install_as_MySQLdb()
app = Flask(__name__)
# 连接数据库
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:admin@127.0.0.1:3306/flask_db"
# 自动追踪程序的修改 一般不跟踪
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
# 数据库操作自动提交
# app.config["SQLALCHEMY_COMMIT_ON_TEARDOWN"] = True
db = SQLAlchemy(app)
migrate = Migrate(app, db)
class HobbyEnum(enum.Enum):
BASKETBALL = 1
BIKE = 2
CLIMB = 3
class Users(db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), nullable=False)
age = db.Column(db.Integer)
email = db.Column(db.String(120), unique=True)
hobby = db.Column(db.Enum(HobbyEnum), default=HobbyEnum.BASKETBALL)
def __init__(self, username, age, email, hobby):
self.username = username
self.age = age
self.email = email
self.hobby = hobby
def __str__(self):
return '<Users: %s>' % self.username
# 将创建好的实体类映射至数据库
# db.create_all()
# db.drop_all()
if __name__ == '__main__':
app.run(debug=True)
执行如下命令:
flask db init // 数据表初始化,会在当前项目生成一个migrations文件夹
flask db migrate -m "init db" // 生成迁移文件,并写上注释
flask db upgrade // 迁移到数据库
flask db downgrade // 撤销迁移操作, 回退到上一次迁移状态
效果如下:
flask-migrate和flask-script配合使用
定义项目结构如下:
# settings.py
DATABASE = {
"USER": "root",
"PASSWORD": "admin",
"HOST": "127.0.0.1",
"PORT": "3306",
"NAME": "flask_db1"
}
DB_URI = "mysql://{USER}:{PASSWORD}@{HOST}:{PORT}/{NAME}" .format(**DATABASE)
SQLALCHEMY_DATABASE_URI = DB_URI
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_COMMIT_ON_TEARDOWN = False
# db_engine.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
# models.py
import enum
from db_engine import db
class HobbyEnum(enum.Enum):
BASKETBALL = 1
BIKE = 2
CLIMB = 3
class Users(db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), nullable=False, doc="用户名")
age = db.Column(db.Integer)
email = db.Column(db.String(120), unique=True)
hobby = db.Column(db.Enum(HobbyEnum), default=HobbyEnum.BASKETBALL)
def __init__(self, username, age, email, hobby):
self.username = username
self.age = age
self.email = email
self.hobby = hobby
def __str__(self):
return '<Users: %s>' % self.username
# app.py
from flask import Flask
import pymysql
from db_engine import db
import settings
pymysql.install_as_MySQLdb()
def create_app():
app = Flask(__name__)
app.config.from_object(settings) # 载入settings.py中的配置信息
db.init_app(app) # app绑定数据库db
return app
if __name__ == '__main__':
app = create_app()
app.run(debug=True)
# manage.py
from flask_migrate import Migrate, MigrateCommand
from db_engine import db
from flask_script import Manager, Server
from app import create_app
# 导入要migrate表
import models
app = create_app() # 实例化一个app对象
manager = Manager(app) # 实例化一个manager对象
Migrate(app=app, db=db) # 绑定 数据库与app,建立关系
manager.add_command('db', MigrateCommand) # 添加迁移命令集到脚本命令
# 如果是以此脚本作为主脚本程序,就执行
if __name__ == '__main__':
manager.run({"runserver": Server(port=8000, host="0.0.0.0")})
执行命令如下:
python manage.py db init
python manage.py db migrate
python manage.py db upgrade
执行效果同上