Flask#DB Migrate

今回はFlask-Migrateの使え方についてメモします。まずFlask-Migrateはなんなのか公式ドキュメントをみてみると…

Flask-Migrate is an extension that handles SQLAlchemy database migrations for Flask applications using Alembic. The database operations are made available through the Flask command-line interface or through the Flask-Script extension.

うんうん、いわゆるFlaskのExtensionの一つでSQLAlchemyのデータベースをマイグレーションを簡単にできるってことですね〜あとこの操作はFlaskのコマンドラインかFlask-Script Extensionかのことかな。まずFlask-Migrateをインストールしましょう。

pip install Flask-Migrate

次はFile構成:

  • Web
    • Manger.py

いまのFile構成はこんな感じですね、WebのFolderの下にManger.pyがあります。Manger.pyはどんなコードが入ってるかどういうど…

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

from flask_script import Manager
from flask_migrate import Migrate,MigrateCommand

app=Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
db=SQLAlchemy(app)

migrate=Migrate(app,db)
manager=Manager(app)

manager.add_command('db',MigrateCommand)

class Person(db.Model):
	id=db.Column(db.Integer,primary_key=True)
	name=db.Column(db.String(20))
	email=db.Column(db.String(120))
	address=db.Column(db.String(120),nullable=False)
	tel=db.Column(db.String(20),nullable=False)
	password=db.Column(db.String(60),nullable=False)
	spare1=db.Column(db.String(21))

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

いまはFolderがDBさえ入ってはい状態でManger.pyを走ってみよう。

python Manger.py db init

Terminalでいろいろなメッセージが出てきて、終わったらFile構成がこうなります。

  • Web
    • Manger.py
    • migrations←

migrationsというFolderが増えてきました。じゃ次はのコマンドを走りましょう。

python Manger.py db migrate

INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.autogenerate.compare] Detected added table 'person'
Generating /Users/chrischung/Google Drive/Web/migrations/versions/c1cc8fa0d2c6_.py ... done

って感じですね。ほ、私が新しいTableを追加してたと気ついてたね〜そしてmigrations/versions/の中に一つのpyスクリプトが追加された。じゃこのc1cc8fa0d2c6.pyがなにが入ってるですか?

"""empty message

Revision ID: c1cc8fa0d2c6
Revises:
Create Date: 2018-07-24 05:30:05.947666

"""
from alembic import op
import sqlalchemy as sa

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

def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
 op.create_table('person',
 sa.Column('id', sa.Integer(), nullable=False),
 sa.Column('name', sa.String(length=20), nullable=True),
 sa.Column('email', sa.String(length=120), nullable=True),
 sa.Column('address', sa.String(length=120), nullable=False),
 sa.Column('tel', sa.String(length=20), nullable=False),
 sa.Column('password', sa.String(length=60), nullable=False),
 sa.Column('spare1', sa.String(length=21), nullable=True),
 sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###

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

Manger.pyの中に定義されたClassがここでDBに入れるってわけですね。じゃ最後のコマンドを走りましょう。

python Manger.py db upgrade
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> c1cc8fa0d2c6, empty message
  • Web
    • Manger.py
    • migrations
    • test.db←

おお、DBが作成されました!じゃ、最後はsqlite3コマンドで確認しましょうか。

sqlite3 test.db

sqlite>.schema

CREATE TABLE person (
	id INTEGER NOT NULL, 
	name VARCHAR(20), 
	email VARCHAR(120), 
	address VARCHAR(120) NOT NULL, 
	tel VARCHAR(20) NOT NULL, 
	password VARCHAR(60) NOT NULL, 
	spare1 VARCHAR(21), 
	PRIMARY KEY (id)
);

OK、それで大丈夫だね。次はManger.pyにもうひとつのTableを追加しましょう。

class tempClass(db.Model):
	id=db.Column(db.Integer,primary_key=True)
	title=db.Column(db.String(20))

そしてもう一度コマンドを走ります。

python Manger.py db migrate

INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'temp_clasee'
  Generating /Users/chrischung/Google Drive/Web/migrations/versions/6c77edaef8c4_.py ... done

python Manger.py db upgrade

INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade c1cc8fa0d2c6 -> 6c77edaef8c4, empty message

どうやらうまくいけそうですね。

sqlite3 test.db
sqlite>.schema

CREATE TABLE person (
	id INTEGER NOT NULL, 
	name VARCHAR(20), 
	email VARCHAR(120), 
	address VARCHAR(120) NOT NULL, 
	tel VARCHAR(20) NOT NULL, 
	password VARCHAR(60) NOT NULL, 
	spare1 VARCHAR(21), 
	PRIMARY KEY (id)
);
CREATE TABLE temp_clasee (
	id INTEGER NOT NULL, 
	title VARCHAR(20), 
	PRIMARY KEY (id)
);

うん、それは大丈夫だね!


実はいくつの問題がありますが…

  • Tableの内容が修正されてMigrateしてもなにも変わらない。
    • ネットでみたらどうやら100%修正したものをDetectできるわけでもないらしいのでmigrateのコマンド走ったあとは必ずそのとき作成されたpyを一回みること。
  • nullable=Falseのコラムがupgradeコマンド走るときはエラー出る問題

それじゃねー

Footer_Basic

Please Support some devices for my blog

Amazon Gift List

Find ME

Twitter:@3threes2
Email:soup01threes*gmail.com (* to @)
YoutubeChannel:https://www.youtube.com/channel/UCQ3CHGAIXZAbeOC_9mjQiWQ

シェアする

  • このエントリーをはてなブックマークに追加

フォローする