Flask-Migrate是一个为Flask应用处理SQLAlchemy数据库迁移的扩展,使得可以通过Flask的命令行接口或者Flask-Scripts对数据库进行操作。
pip install flask-migrate
app = Flask(__name__)
app.config.from_envvar('config.py')
db = SQLAlchemy(app)
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
python script.py db init
python script.py db migrate -m "版本名后缀"
python script.py db upgrade
mysql -uroot -pwestos
python script.py db history
python script.py db downgrade base
python data_migrate.py db current
python data_migrate.py db upgrade 版本号
python data_migrate.py db --help
设计结构:
|-- app
| |-- forms.py
| |-- __init__.py
| |-- manageUtil
| | |-- database.py
| | `-- __pycache__
| | `-- database.cpython-36.pyc
| |-- models.py
| |-- __pycache__
| | |-- __init__.cpython-36.pyc
| | |-- models.cpython-36.pyc
| | `-- views.cpython-36.pyc
| |-- static
| |-- templates
| | `-- list.html
| `-- views.py
|-- config.py
`-- manage.py
应用到上一篇文章的数据库里
在__init__.py文件中实例化Migrate对象
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bootstrap import Bootstrap
import pymysql
from flask_script import Manager
from flask_migrate import Migrate
pymysql.install_as_MySQLdb()
app = Flask(__name__)
app.config.from_pyfile('../config.py')
db = SQLAlchemy(app)
bt = Bootstrap(app)
manager = Manager(app)
migrate = Migrate(app, db)
在manage.py文件中加入命令
from flask_migrate import MigrateCommand
from app import app, manager, db
from app.managerUtil.database import database_manager
from app.views import *
from flask_script import Command, prompt_bool
# 添加其他的命令到manager里面来
manager.add_command('database', database_manager)
manager.add_command('db', MigrateCommand)
if __name__ == '__main__':
# app.run(port=5006)
manager.run()
为了代码完整我们把之前的复制过来:
database.py
from flask_script import Manager, prompt_bool, Command
from app import db
from app.models import User, Role
database_manager = Manager(usage="数据库的操作详情")
# 1. 方法一: 类的继承
class AddUser(Command):
"""添加用户"""
def run(self):
u = User(username="fentiao90009", password="fentiao", email="[email protected]")
db.session.add(u)
db.session.commit()
return "正在添加用户%s........" % (u.username)
# 添加类到命令中, 让manger进行管理
database_manager.add_command('adduser', AddUser)
# 2. 通过装饰器@database_manager.command
@database_manager.command
def deleteUser():
"""删除用户"""
u = User.query.filter_by(username='fentiao90009').first()
if u:
db.session.delete(u)
db.session.commit()
return "删除用户%s成功....." % (u.username)
else:
return "删除用户失败:"
# 3). option装饰器, 可以指定参数
@database_manager.option('-u', '--username', help="指定用户名")
@database_manager.option('-p', '--password', help="指定密码")
def add_user(username, password):
"""添加用户, 指定用户名和密码"""
if username and password:
u = User(username=username, password=password)
db.session.add(u)
db.session.commit()
return "添加用户%s成功" %(u.username)
else:
return "请指定用户名和密码"
@database_manager.command
def dropdb():
"""删除数据库"""
if prompt_bool("是否删除数据库"):
db.drop_all()
@database_manager.command
def createdb():
"""创建数据库"""
if prompt_bool("是否创建数据库"):
db.create_all()
@database_manager.command
def recreate():
"""重建数据库"""
if prompt_bool("是否重数据库"):
dropdb()
createdb()
@database_manager.command
def init_data():
"""初始化数据库"""
role = Role(name="管理员")
db.session.add(role)
for user in range(100):
u = User(username="westos%s" %(user), password="hello", email="westos%[email protected]" %(user),role_id=1)
db.session.add(u)
db.session.commit()
print("初始化完成")
models.py
### 用户和角色是什么关系?
# - 一对一
# - 一对多: 角色是一, 用户是多, 外键写在多的一端
# - 多对多
from datetime import datetime
from app import db
class Role(db.Model):
__tablename__ = "用户角色"
# id号递增autoincrement=True
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(20))
# 反向引用, Role表中有属性users, User类中有role这个属性;
users = db.relationship('User', backref='role')
def __repr__(self):
return "" % (self.name)
class User(db.Model):
__tablename__ = "网站用户"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(30), unique=True, index=True, nullable=False) # unique=True用户名不能重复
password = db.Column(db.String(20), nullable=False)
email = db.Column(db.String(20), unique=True, index=True)
# 设置默认值, 位当前用户的创建时间;
add_time = db.Column(db.DateTime, default=datetime.now())
#### 重要的: 用户角色id不能随便设置, 需要从Role中查询, (外键关联)
role_id = db.Column(db.Integer, db.ForeignKey('用户角色.id'))
# 定义了 __repr()__ 方法,返回一个具有可读性的字符串表示模型,可在调试和测试时使用。
def __repr__(self):
return "" % (self.username)
views.py
# http://www.csdn.net/list/
# http://www.csdn.net/list/1/
# http://www.csdn.net/list/2/
from flask import render_template
from app import app
from app.models import User
@app.route('/list/')
@app.route('/list//')
def list(page=1):
# 每页显示的数据
per_page = 10
# 返回的是 Pagination对象
userPageObj = User.query.paginate(page=page, per_page=per_page)
return render_template('list.html',
userPageObj=userPageObj
)
config.py
SQLALCHEMY_DATABASE_URI = 'mysql://root:redhat@localhost/UserTest'
SQLALCHEMY_TRACK_MODIFICATIONS = True
python script.py db init
现在给models.py中的加上性别gender属性
### 用户和角色是什么关系?
# - 一对一
# - 一对多: 角色是一, 用户是多, 外键写在多的一端
# - 多对多
from datetime import datetime
from app import db
class Role(db.Model):
__tablename__ = "用户角色"
# id号递增autoincrement=True
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(20))
# 反向引用, Role表中有属性users, User类中有role这个属性;
users = db.relationship('User', backref='role')
def __repr__(self):
return "" % (self.name)
class User(db.Model):
__tablename__ = "网站用户"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(30), unique=True, index=True, nullable=False) # unique=True用户名不能重复
password = db.Column(db.String(20), nullable=False)
email = db.Column(db.String(20), unique=True, index=True)
# 设置默认值, 位当前用户的创建时间;
add_time = db.Column(db.DateTime, default=datetime.now())
# 1-男 2-女
gender = db.Column(db.SmallInteger,default=2)
#### 重要的: 用户角色id不能随便设置, 需要从Role中查询, (外键关联)
role_id = db.Column(db.Integer, db.ForeignKey('用户角色.id'))
# 定义了 __repr()__ 方法,返回一个具有可读性的字符串表示模型,可在调试和测试时使用。
def __repr__(self):
return "" % (self.username)
python manage.py db migrate -m “添加用户性别” #读取类的内容, 生成版本文件, 并没有真正在数据库中添加或删除;
自动生成一个目录
读取类的内容, 生成版本文件, 并没有真正在数据库中添加或删除;
python manage.py db migrate -m "添加用户性别"
在数据库中增删改, 也就是将迁移应用于数据库;
python manage.py db upgrade
添加年龄,models.py修改
### 用户和角色是什么关系?
# - 一对一
# - 一对多: 角色是一, 用户是多, 外键写在多的一端
# - 多对多
from datetime import datetime
from app import db
class Role(db.Model):
__tablename__ = "用户角色"
# id号递增autoincrement=True
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(20))
# 反向引用, Role表中有属性users, User类中有role这个属性;
users = db.relationship('User', backref='role')
def __repr__(self):
return "" % (self.name)
class User(db.Model):
__tablename__ = "网站用户"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(30), unique=True, index=True, nullable=False) # unique=True用户名不能重复
password = db.Column(db.String(20), nullable=False)
email = db.Column(db.String(20), unique=True, index=True)
# 设置默认值, 位当前用户的创建时间;
add_time = db.Column(db.DateTime, default=datetime.now())
# 1-男 2-女
gender = db.Column(db.SmallInteger,default=2)
age = db.Column(db.Integer)
#### 重要的: 用户角色id不能随便设置, 需要从Role中查询, (外键关联)
role_id = db.Column(db.Integer, db.ForeignKey('用户角色.id'))
# 定义了 __repr()__ 方法,返回一个具有可读性的字符串表示模型,可在调试和测试时使用。
def __repr__(self):
return "" % (self.username)
python manage.py db migrate -m "添加年龄"
python manage.py db upgrade
python manage.py db downgrade base # 返回指定的版本状态;降级数据库,不指定版本则是最老版本
查看数据库,发现之前添加的age gender不见了,降级成功