python-flask(五)-Flask-Migrate数据库迁移

1. 什么是Flask-Migrate?

Flask-Migrate是一个为Flask应用处理SQLAlchemy数据库迁移的扩展,使得可以通过Flask的命令行接口或者Flask-Scripts对数据库进行操作。

2. 如何安装Flask-Migrate?

pip install flask-migrate

3. 如何配置?

app = Flask(__name__)

app.config.from_envvar('config.py')
db = SQLAlchemy(app) 

migrate = Migrate(app, db)

manager = Manager(app)
manager.add_command('db', MigrateCommand)

4. 如何使用?

  • 1). 创建迁移仓库(migrations目录)
python script.py  db init
  • 2). 读取类的内容, 生成版本文件, 并没有真正在数据库中添加或删除;
python  script.py  db migrate -m "版本名后缀"
  • 3). 在数据库中增删改, 也就是将迁移应用于数据库;
python script.py  db upgrade
  • 4). 检测是否成功?
mysql -uroot -pwestos
  • 5). 去查看改变的历史状态;
python script.py  db history
  • 6). 返回指定的版本状态;降级数据库,不指定版本则是最老版本
python script.py  db downgrade  base
  • 7). 显示当前版本
python data_migrate.py db current 
  • 8). 升级版本,不指定版本为最新版本
python data_migrate.py db upgrade 版本号
  • 7). 帮助,查找所有命令
python data_migrate.py db --help 

5.数据库迁移实验

设计结构:

|-- 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 "<Role %s>" % (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 "<User %s>" % (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/<int:page>/')
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

在这里插入图片描述
1.创建迁移仓库

python script.py  db init

在这里插入图片描述会生成一个migrations目录:
在这里插入图片描述

数据库里没有gender
在这里插入图片描述

现在给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 "<Role %s>" % (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 "<User %s>" % (self.username)

python manage.py db migrate -m “添加用户性别” #读取类的内容, 生成版本文件, 并没有真正在数据库中添加或删除;
在这里插入图片描述自动生成一个目录
在这里插入图片描述

读取类的内容, 生成版本文件, 并没有真正在数据库中添加或删除;

python manage.py  db migrate -m "添加用户性别"

在数据库中增删改, 也就是将迁移应用于数据库;

 python manage.py  db upgrade 

查看表中,更新了gender
在这里插入图片描述

添加年龄,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 "<Role %s>" % (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 "<User %s>" % (self.username)
python manage.py  db migrate -m "添加年龄"
python manage.py  db upgrade

在这里插入图片描述在这里插入图片描述

 python manage.py  db downgrade base # 返回指定的版本状态;降级数据库,不指定版本则是最老版本

在这里插入图片描述在这里插入图片描述

查看数据库,发现之前添加的age gender不见了,降级成功

猜你喜欢

转载自blog.csdn.net/weixin_43067754/article/details/88578164
今日推荐