LoginSignup
0
0

More than 1 year has passed since last update.

Flask Migration 五月雨メモ

Last updated at Posted at 2021-09-16

Flask の Migration を使ってみたのでいろいろメモ。

とりあえず最短で動くまでを構築している。DB は PostgreSQL
フォルダ構成は

├main.py
├config.py
└📁models
  ├database.py
  ├user.py

みたいな感じで、models フォルダにモデルを分離した。チュートリアルとかだと、main.py にべた書きしているのが多くて少しだけ手間取った。

database.py にセッション初期化の関数を用意して

models/database.py
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def init_db(app):
    db.init_app(app)

config.py には接続情報を用意する。

config.py
import os

class DevelopmentConfig:
    SQLALCHEMY_TRACK_MODIFICATIONS = True
    SQLALCHEMY_ECHO = True
    SQLALCHEMY_DATABASE_URI = 'postgresql+psycopg2://{user}:{password}@{host}/{name}'.format(**{
        'user': 'postgres',
        'password': 'password',
        'host': 'localhost:5432',
        'name': 'postgres'
    })

Config = DevelopmentConfig

そして、メインはこうなる。

main.py
from models.user import User
from models.database import db, init_db

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

init_db(app)

migrate = Migrate(app, db)

<中略>

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

チュートリアルなどを見ていると db.create_all() という関数を呼んでいるものがあるが、これはマイグレーションをしないで一括で作成してそのままそれをつかう開発の時で、マイグレーションをしたい場合には使えない。マイグレーションで DB を作成したい場合は、コマンドラインで操作する。

その前に、毎回打つのも冗長なので、環境変数に FLASK_APP=manage.py を入れておく。

export FLASK_APP=manage.py

次に、マイグレーションファイルを作成するので初回は初期化する。このコマンドでmigrationsというフォルダが生成される。

flask db init

マイグレーションを実行するとテーブルも作成されます。

flask db migrate

ここで注意。 モデルで外部キーを使っている場合、外部キーの参照先のモデルをインポートしておく必要があります 。あたりまえといえばあたりまえなんだけど、チュートリアルなどで書かれているサンプルだと、同じファイルに全部のモデルが書いてあったりするので意外と気づきにくい。

下記の例だとユーザ(User)が契約(Contract)テーブルに外部キー参照を持っているので、contract をインポートする必要がある。

user.py
from models.database import db
from models.contract import Contract #←これが必要だよ!!!!!

class User(db.Model):
    __tablename__ = 'User'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    create_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    update_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)

    contract_id = db.Column(db.Integer, db.ForeignKey('Contract.id'))
    email = db.Column(db.String(255), nullable=True)

    def __init__(self, sumaregi_user_id, contract_id):
        self.contract_id = contract_id

その他メモ

文字数制限のないテキスト型

Text というのがある

    email = db.Column(db.Text, nullable=True)

型を修正してマイグレーションしても反映されないとき

Migrate に compare_type=True オプションを付ける必要がある。

migrate = Migrate(app, db, compare_type=True)
0
0
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
0
0