Flask数据库迁移:Flask-Migrate和Flask-Script的使用

在程序开发过程中,我们难以避免会对数据库表结构进行修改,而每一次修改,都可能会影响到已经完成的程序,很多语言中都有数据库迁移的概念,数据库迁移可以用一种非常优雅的方式来帮助我们完成数据库更新,极大的方便我们的开发。

Flask-Migrate是一个Flask扩展,用于处理数据库迁移。Flask-Script也是一个Flask扩展,用于提供自定义的运行脚本。一般情况下,Flask-Migrate结合Flask-Script使用,让数据库操作可以通过命令行方式来执行。

本文将通过一个实例来演示Flask-Migrate和Flask-Script的使用。

一、Flask环境搭建

首先要完成Flask环境搭建,可参考《Flask环境搭建及基础项目构建》

二、Flask应用配置及建立数据模型

首先肯定要做数据库配置,数据库配置可以参考

《Flask使用Flask-SQLAlchemy操作MySQL数据库(一)——Flask-SQLAlchemy配置与数据库连接》

不过为了使代码结构更清晰,这里使用另一种配置方式,即使用单独配置文件的文件来做全局Flask配置。

1、配置

首先要安装数据库操作所需要的扩展:

pip install flask-mysqldb

pip install flask-sqlalchemy

在项目中新建config.py配置文件,将相关的数据库信息、连接等信息写入配置文件。

DB_USER = 'root'
DB_PASSWORD = ''
DB_HOST = 'localhost'
DB_DB = 'test'

DEBUG = True

SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_DATABASE_URI = 'mysql://' + DB_USER + ':' + DB_PASSWORD + '@' + DB_HOST + '/' + DB_DB

2、定义SQLAlchemy实例及数据模型

在前面的文章中,在使用Flask-SQLAlchemy数据库操作时,我们需要定义SQLAlchemy实例和数据模型,在数据库迁移时,也是一样的。本文要完成一个数据库迁移及接口实现的完整过程,鉴于在数据库迁移和接口实现中都会用到数据模型,这里把数据模型单独抽取出来,作为单独文件,以备手续复用。

新建model.py,并定义一个用户表数据模型:

from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class User(db.Model):
    user_id = db.Column(db.Integer, primary_key=True)
    user_name = db.Column(db.String(60), nullable=False)
    user_password = db.Column(db.String(30), nullable=False)
    user_nickname = db.Column(db.String(50))
    user_email = db.Column(db.String(30), nullable=False)

完成上面步骤,接下来就可以来配置完成数据库迁移了。

三、数据库迁移配置

1、安装Flask-Migrate和Flask-Script

pip install flask-migrate

pip install flask-script

2、新建迁移配置文件db.py

文件代码如下:

from flask import Flask
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from model import db

app = Flask(__name__)
app.config.from_object('config')

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

if __name__ == '__main__':
    manager.run()

上面的代码中,使用Flask-Script整合Flask-Migrate,添加自定义操作命令”db”来实现数据库迁移。

3、迁移命令

python db.py db init

python db.py db migrate

python db.py db upgrade

运行上面命令后,可以看到数据库test中新建了一个user表,表结构就是数据模型model.py中定义的数据结构。

四、示例接口实现

接下来,完整示例程序,加上接口实现代码。

整个示例程序文件结构(一共四个文件)和代码如下:

from flask import Flask, jsonify, request
from model import db, User

app = Flask(__name__)
app.config.from_object('config')

db.init_app(app)

@app.route('/')
def index():
    return '<h1>Hello Flask!</h1>'

@app.route('/user', methods=['POST'])
def addUser():
    user_name = request.form.get('user_name')
    user_password = request.form.get('user_password')
    user_nickname = request.form.get('user_nickname')
    user_email = request.form.get('user_email')
    user = User(user_name=user_name, user_password=user_password, user_nickname=user_nickname,
                user_email=user_email)
    try:
        db.session.add(user)
        db.session.commit()
    except:
        db.session.rollback()
        db.session.flush()
    userId = user.user_id
    if (user.user_id is None):
        result = {'msg': '添加失败'}
        return jsonify(data=result)
    data = User.query.filter_by(user_id=userId).first()
    result = {'user_id': data.user_id, 'user_name': data.user_name, 'user_nickname': data.user_nickname,
              'user_email': data.user_email}
    return jsonify(data=result)

@app.route('/user/<int:userId>', methods=['GET'])
def getUser(userId):
    user = User.query.filter_by(user_id=userId).first()
    if (user is None):
        result = {'msg': '找不到数据'}
    else:
        result = {'user_id': user.user_id, 'user_name': user.user_name, 'user_nickname': user.user_nickname,
                  'user_email': user.user_email}
    return jsonify(data=result)

@app.route('/user/<int:userId>', methods=['PATCH'])
def updateUser(userId):
    user_name = request.form.get('user_name')
    user_password = request.form.get('user_password')
    user_nickname = request.form.get('user_nickname')
    user_email = request.form.get('user_email')
    try:
        user = User.query.filter_by(user_id=userId).first()
        if (user is None):
            result = {'msg': '找不到要修改的记录'}
            return jsonify(data=result)
        else:
            user.user_name = user_name
            user.user_password = user_password
            user.user_nickname = user_nickname
            user.user_email = user_email
            db.session.commit()
    except:
        db.session.rollback()
        db.session.flush()
    userId = user.user_id
    data = User.query.filter_by(user_id=userId).first()
    result = {'user_id': data.user_id, 'user_name': data.user_name, 'user_password': data.user_password, 'user_nickname': data.user_nickname, 'user_email': data.user_email}
    return jsonify(data=result)

@app.route('/user', methods=['GET'])
def getUsers():
    data = User.query.all()
    data_all = []
    for user in data:
        data_all.append({'user_id': user.user_id, 'user_name': user.user_name, 'user_nickname': user.user_nickname, 'user_email': user.user_email})
    return jsonify(users=data_all)

@app.route('/user/<int:userId>', methods=['DELETE'])
def deleteUser(userId):
    # 删除数据
    User.query.filter_by(user_id=userId).delete()
    db.session.commit()
    return getUsers()

if __name__ == '__main__':
    app.run(debug=app.config['DEBUG'])

本文完

 

那时那我

随遇,随缘,随安,随喜!

2 thoughts to “Flask数据库迁移:Flask-Migrate和Flask-Script的使用”

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.