LoginSignup
7
3

More than 5 years have passed since last update.

Flask#DB Migrate

Last updated at Posted at 2018-07-23

原文は私が書いてるBlogにのってます。よろしくおねがいします
http://soup01.com/ja/2018/07/24/flaskdb-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/user/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():
 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')
)


def downgrade():
 op.drop_table('person')

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/user/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コマンド走るときはエラー出る問題

それじゃねー

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3