いつも行っていることをまとめる。
参考にするドキュメント
- Welcome to Flask — Flask Documentation (0.12)
- SQLAlchemy - The Database Toolkit for Python
- Flask-SQLAlchemy — Flask-SQLAlchemy Documentation (2.3)
今回の利用した環境は以下の通り。
- MacOS 10.13.3
- Python 3.6.3
- flask 0.12.2
- flask-sqlalchemy 2.3.2
- PyMySQL 0.8.0
- SQLAlchemy 1.2.2
必要なライブラリをインストールする
- flask
- SQLAlchemy
- flask-sqlalchemy
- pymysql
をインストールする。
$ pip install flask SQLAlchemy flask-sqlalchemy PyMySQL
アプリ初期構築
アプリの初期構築を行う。
Flaskは自由度が高いのでアプリのディレクトリ構成は様々な形を取ることができるが、以下はその一例。この例に沿って以下話を進める。
├── flask_sample
│ ├── app.py
│ ├── config.py
│ └── database.py
└── run.py
flask_sample/database.py
"""FlaskアプリがSQLAlchemyを使えるようにするための初期化"""
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def init_db(app):
db.init_app(app)
flask_sample/config.py
"""FlaskのConfigを提供する"""
import os
class DevelopmentConfig:
# Flask
DEBUG = True
# SQLAlchemy
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://{user}:{password}@{host}/flask_sample?charset=utf8'.format(**{
'user': os.getenv('DB_USER', 'root'),
'password': os.getenv('DB_PASSWORD', ''),
'host': os.getenv('DB_HOST', 'localhost'),
})
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = False
Config = DevelopmentConfig
※1 上記の SQLALCHEMY_DATABASE_URI
は、DriverにPyMySQLを利用した場合の書き方になっている。PyMySQLとは別のDriverを用いる場合は別の設定にする必要がある。詳しくはリンク先ページ参照。 http://docs.sqlalchemy.org/en/latest/dialects/mysql.html
※2 今回Database名を flask_sample
としている。当然MySQLからCREATE DATABASE文を使ってDatabaseを先に作っておく必要がある。(Databaseの作成方法は割愛)
flask_sample/app.py
"""flask appの初期化を行い、flask appオブジェクトの実体を持つ"""
from flask import Flask
from flask_sample.database import init_db
def create_app():
app = Flask(__name__)
app.config.from_object('flask_sample.config.Config')
init_db(app)
return app
app = create_app()
run.py
from flask_sample.app import app
if __name__ == '__main__':
app.run()
このアプリを起動する場合は、以下のコマンドを実行する。
$ python run.py
あるいは環境変数FLASK_APP
を定義してflask
コマンドを利用することでもアプリを起動することができる。
$ FLASK_APP=run.py flask run
これでFlaskでSQLAlchemyを利用する基本的な準備は整った。
Modelを一つ作ってみる
実際にModelクラスを一つ作ってみることにする。
Modelクラスの定義
以下のように flask_sample/models
以下を用意する。
flask_sample
├── app.py
~
└── models
├── __init__.py
└── models.py
flask_sample/models/models.py
from datetime import datetime
from flask_sample.database import db
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255), nullable=False)
created_at = db.Column(db.DateTime, nullable=False, default=datetime.now)
updated_at = db.Column(db.DateTime, nullable=False, default=datetime.now, onupdate=datetime.now)
flask_sample/models/__init__.py
from .models import User
__all__ = [
User,
]
そして、appがロードされた時にこのUserクラスもloadされるように、flask_sample/app.py
内でUserクラスをimportするようにする。
from flask import Flask
from flask_sample.database import init_db
import flask_sample.models
...
テーブルの作成
※2019/01/03追記
この直後に説明するFlask-Migrate
を使ったMigrationを実施する場合は、ここで説明しているdb.create_all()
を使ったテーブルの作成は行うべきではありません。
Flask-Migrate
ではテーブルの状態管理をしており、Flask-Migrate
を使わずにテーブル作成した場合、未知の状態を与えてしまうためです。もし、Flask-Migrate
を利用する予定の場合はこの項の説明を読み飛ばして次の説明を読み進めることをおすすめします。
参考issue
https://github.com/miguelgrinberg/Flask-Migrate/issues/173
Modelクラスを用意したら、次にDatabaseにテーブルを作成する。
テーブルを作成するには SQLAlchemy.create_all()
を呼び出す。これでimportされているModelクラスのテーブルが全て作成される。
$ FLASK_APP=run.py flask shell
Python 3.6.3 (default, Jan 8 2018, 18:42:55)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
App: flask_sample.app [debug]
Instance: ~/flask-sample/instance
>>> from flask_sample.database import db
>>> db.create_all()
これで users
テーブルが作成された。
migrationを行うには
直前の手順で、定義しているModelクラスに関するテーブルが作成されたわけだが、都度手動で db.create_all()
を呼び出してテーブルを定義するには少し面倒が多く、きちんとschemaのバージョン管理を行うことも含めてMigrationの導入を行う。
Flask + SQLAlchemy でMigrationを行うには Flask-Migrate を使うと便利。
Flask-Migrateのインストール
pipでインストール可能。
$ pip install Flask-Migrate
Flask-Migrateを使う
Flask-Migrateを使うには、flask_migrate.Migrate
にflaskオブジェクトと flask_sqlalchemy.SQLAlchemy
オブジェクトを食わせることでFlask-MigrateのCLIコマンドを使うことが可能になる。以下は上記までのサンプル上でFlask-Migrateを使う場合の例。
flask_sample/database.py
"""FlaskアプリがSQLAlchemyとFlask-Migrateを使えるようにするための初期化"""
from flask_sqlalchemy import SQLAlchemy
from flask_sample.database import init_db
from flask_migrate import Migrate # 追加
db = SQLAlchemy()
def init_db(app):
db.init_app(app)
Migrate(app, db) # 追加
こうした後では flask db
コマンドが利用可能になる。
$ FLASK_APP=run.py flask db init
Flask-Migrateのコマンド例
最低限のコマンド例を示す。
https://flask-migrate.readthedocs.io/en/latest/#command-reference
こちらにコマンドリファレンスがあるので、これで利用可能なコマンドの全貌がわかる。
※以下のコマンド例は環境変数 FLASK_APP
を適切に設定している場合における場合。
初期化
$ flask db init
migrations
ディレクトリが作成され、その中で必要なファイルが設置される。
migrationファイルの作成
$ flask db migrate
modelクラスの定義を見て、差分をmigrationファイルとして作成する。(まだmigrationの適用はされない)
migrationの実行
$ flask db upgrade
未実行のmigrationを実行する。
migrationのrollback
$ flask db downgrade
一つ前のバージョンに戻す。
まとめ
- Flaskアプリの初期構築
- Flask-SQLAlchemyの使い方(Model定義)
- Flask-Migrateの使い方
を簡単に説明した。これでベーシックなFlask + SQLAlchemyを使ったアプリケーション構築のための準備が整った。
追加でこれをしていくといいよ、というのがあればどしどし。