flask-migrate動(dòng)態(tài)遷移數(shù)據(jù)庫(kù)

了解flask_migrate需要先了解flask-script,那么flask-script的作用是什么呢?flask-script的作用是可以通過(guò)命令行的形式來(lái)操作Flask。例如通過(guò)命令跑一個(gè)開(kāi)發(fā)版本的服務(wù)器、設(shè)置數(shù)據(jù)庫(kù),定時(shí)任務(wù)等。

2.執(zhí)行pip install flask-script來(lái)進(jìn)行安裝。

  1. 如果直接在主manage.py中寫(xiě)命令,那么在終端就只需要python manage.py command_name就可以了。
  2. 如果把一些命令集中在一個(gè)文件中,那么在終端就需要輸入一個(gè)父命令,比如python manage.py db init。

app.py文件

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

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

manager.py文件

# encoding: utf-8

from flask_script import Manager
from app import app

manager = Manager(app)

@manager.command
def run():
    print("服務(wù)器跑起來(lái)了")

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

在終端運(yùn)行,run代表的是manager.py中的方法

python manage.py run
服務(wù)器跑起來(lái)了

flask-script我們一般和數(shù)據(jù)庫(kù)在一起使用

app.py文件

#encoding: utf-8

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run(debug=True)

manage.py文件

#encoding: utf-8

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'Hello World!'


if __name__ == '__main__':
    app.run(debug=True)

db_scripts.py文件

# encoding: utf-8

from flask_script import Manager

DBManager = Manager()

@DBManager.command
def init():
    print('數(shù)據(jù)庫(kù)初始化完成')

@DBManager.command
def migrate():
    print('數(shù)據(jù)表遷移成功')

首先執(zhí)行如下命令:

python manage.py db init
數(shù)據(jù)庫(kù)初始化完成

再執(zhí)行命令

python manage.py db migrate
數(shù)據(jù)表遷移成功

上面使用flask-script的使用以及對(duì)數(shù)據(jù)庫(kù)的演示,實(shí)際開(kāi)發(fā)中我們使用flask-migrate來(lái)動(dòng)態(tài)的遷移數(shù)據(jù)庫(kù),使用flask-migrate必須借助flask-script。

Flask-Migrate的介紹與安裝:

pip install flask-migrate

搞起?。?!

migrate_demo.py文件

from flask import Flask
import config
from exts import db

app = Flask(__name__)
app.config.from_object(config)
db.init_app(app)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run(debug=True)

exts.py文件

from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()

config.py文件

DIALECT = 'mysql'
DRIVER = 'pymysql'
USERNAME = 'root'
PASSWORD = '123456'
HOST = '127.0.0.1'
PORT = '3306'
DATABASE = 'pythonflask'

SQLALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(DIALECT, DRIVER, USERNAME, PASSWORD, HOST, PORT,
                                                                       DATABASE)
SQLALCHEMY_TRACK_MODIFICATIONS = False

models.py

from exts import db

class Article(db.Model):
    __tablename__ = 'article'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(100), nullable=False)
    content = db.Column(db.Text, nullable=False)

manage.py,這個(gè)是最重要的文件:

from flask_script import Manager
from migrate_demo import app
from flask_migrate import Migrate,MigrateCommand
from exts import db
from models import Article

manager = Manager(app)
# 1. 要使用flask_migrate,必須綁定app和db
migrate = Migrate(app,db)
# 2. 把MigrateCommand命令添加到manager中
manager.add_command('db',MigrateCommand)

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

我們使用的是pythonflask這個(gè)數(shù)據(jù)庫(kù),里面沒(méi)有任何的表和數(shù)據(jù)。



  • 終端執(zhí)行命令第一個(gè)命令:
python manage.py db init

上面的命令執(zhí)行后,在我們的項(xiàng)目中會(huì)生成一個(gè)migrations文件夾,如下所示,versions中沒(méi)有任何內(nèi)容:



上面的命令執(zhí)行完后,來(lái)看看數(shù)據(jù)庫(kù)發(fā)生變化沒(méi)有:



可以看出,此時(shí)數(shù)據(jù)庫(kù)沒(méi)有發(fā)生任何變化。
  • 上面的命令成功后,執(zhí)行如下命令,將模型生成遷移文件:
python manage.py db init

如下所示,versions文件夾中生成了一個(gè)文件c6439ddd759f_.py,這個(gè)就是遷移文件。


c6439ddd759f_.py:

from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = 'c6439ddd759f'
down_revision = None
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('article',
    sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
    sa.Column('title', sa.String(length=100), nullable=False),
    sa.Column('content', sa.Text(), nullable=False),
    sa.PrimaryKeyConstraint('id')
    )
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('article')
    # ### end Alembic commands ###

再來(lái)看看數(shù)據(jù)庫(kù)發(fā)生了什么變化:


這時(shí)多了一個(gè)alembic_version文件,這個(gè)文件是遷移文件的版本號(hào)。

  • 接下來(lái)執(zhí)行最后一個(gè)命令,將遷移文件真正的映射到數(shù)據(jù)庫(kù)中:
python manage.py db upgrade

查看數(shù)據(jù)庫(kù)的變化:


可以看出,這個(gè)命令執(zhí)行完后,數(shù)據(jù)才真正的遷移到數(shù)據(jù)庫(kù)了。

現(xiàn)在article中我們可以看到只有如下字段:


那這時(shí)候如果我想再插入一個(gè)字段,該如何操作呢?只需要把上面的命令執(zhí)行一遍就可以,但不是每個(gè)命令都執(zhí)行的。
python manage.py db init:這個(gè)命令不需要執(zhí)行,因?yàn)橐呀?jīng)初始化了遷移腳本的環(huán)境,這個(gè)命令只執(zhí)行一次。

python manage.py db migrate:這個(gè)命令需要執(zhí)行,因?yàn)槟P透淖兞恕?/p>

python manage.py db upgrade這個(gè)命令也需要執(zhí)行,每次運(yùn)行了migrate命令后,就記得要運(yùn)行這個(gè)命令。

增加的這個(gè)字段為“name”:

class Article(db.Model):
    __tablename__ = 'article'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(100), nullable=False)
    name = db.Column(db.String(100), nullable=False)
    content = db.Column(db.Text, nullable=False)

命令執(zhí)行完后,查看數(shù)據(jù)庫(kù):



更新成功了!?。。。。?!

總結(jié)如下:

  1. 介紹:因?yàn)椴捎?code>db.create_all在后期修改字段的時(shí)候,不會(huì)自動(dòng)的映射到數(shù)據(jù)庫(kù)中,必須刪除表,然后重新運(yùn)行db.craete_all才會(huì)重新映射,這樣不符合我們的需求。因此flask-migrate就是為了解決這個(gè)問(wèn)題,它可以在每次修改模型后,可以將修改的東西映射到數(shù)據(jù)庫(kù)中。
  2. 使用flask_migrate必須借助flask_scripts,這個(gè)包的MigrateCommand中包含了所有和數(shù)據(jù)庫(kù)相關(guān)的命令。
  3. flask_migrate相關(guān)的命令:
    • python manage.py db init:初始化一個(gè)遷移腳本的環(huán)境,只需要執(zhí)行一次。
    • python manage.py db migrate:將模型生成遷移文件,只要模型更改了,就需要執(zhí)行一遍這個(gè)命令。
    • python manage.py db upgrade:將遷移文件真正的映射到數(shù)據(jù)庫(kù)中。每次運(yùn)行了migrate命令后,就記得要運(yùn)行這個(gè)命令。
  4. 注意點(diǎn):需要將你想要映射到數(shù)據(jù)庫(kù)中的模型,都要導(dǎo)入到manage.py文件中,如果沒(méi)有導(dǎo)入進(jìn)去,就不會(huì)映射到數(shù)據(jù)庫(kù)中。

最后我們可以隨心所欲的來(lái)對(duì)數(shù)據(jù)庫(kù)進(jìn)行增刪改查了,簡(jiǎn)單的在article中插入一條數(shù)據(jù),修改migrate_demo.py文件:

from flask import Flask

import config
from exts import db
from models import Article

app = Flask(__name__)
app.config.from_object(config)
db.init_app(app)

#  新增數(shù)據(jù)
@app.route('/addData')
def addData():
    article = Article(title='aaaa', content='dsfsdf')
    db.session.add(article)
    db.session.commit()
    return 'Hello World!'

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run(debug=True)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容