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

搞起!A堇薄抱既!

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ù):



更新成功了3衅!!E缚АQ喔搿!L淅薄啊研!

總結(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)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市椿肩,隨后出現(xiàn)的幾起案子瞻颂,更是在濱河造成了極大的恐慌,老刑警劉巖郑象,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贡这,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡厂榛,警方通過(guò)查閱死者的電腦和手機(jī)盖矫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)丽惭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人辈双,你說(shuō)我怎么就攤上這事责掏。” “怎么了湃望?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵拷橘,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我喜爷,道長(zhǎng),這世上最難降的妖魔是什么萄唇? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任檩帐,我火速辦了婚禮,結(jié)果婚禮上另萤,老公的妹妹穿的比我還像新娘湃密。我一直安慰自己,他們只是感情好四敞,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布泛源。 她就那樣靜靜地躺著,像睡著了一般忿危。 火紅的嫁衣襯著肌膚如雪达箍。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 48,970評(píng)論 1 284
  • 那天铺厨,我揣著相機(jī)與錄音缎玫,去河邊找鬼。 笑死解滓,一個(gè)胖子當(dāng)著我的面吹牛赃磨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播洼裤,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼邻辉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了腮鞍?” 一聲冷哼從身側(cè)響起值骇,我...
    開(kāi)封第一講書(shū)人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎移国,沒(méi)想到半個(gè)月后雷客,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡桥狡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年搅裙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了皱卓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡部逮,死狀恐怖娜汁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情兄朋,我是刑警寧澤掐禁,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站颅和,受9級(jí)特大地震影響傅事,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜峡扩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一蹭越、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧教届,春花似錦响鹃、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至强霎,卻和暖如春忿项,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背城舞。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工倦卖, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人椿争。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓怕膛,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親秦踪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子褐捻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容