どうも、Flask学習中の民です。
今回はFlask-SQLAlchemyを使ってデータベースへの接続とテーブルの作成、クエリの作成から送信を行ってみます。
この記事はテーブルの作成までです。クエリの送信に関しては下記をご確認ください。
FlaskアプリのDBをFlask-SQLAlchemyで構築する(後編)
※近日公開します
前提
この記事は下記を教材として学習する過程で書いたものです。
『Flask Web Development Developing Web Applications with Python』 Miguel Grinberg
FlaskでWebアプリを作る際に必要となるDB構築の初歩について書きます。
前提は
・PostgreSQLを利用(MySQL、SQLiteでも対して変わりません)
・PostgreSQLとロールとデータベースは作成済み
です。
Flask-SQLAlchemyの導入と環境設定
DBの構築に対してはFlask-SQLAlchemyというFlask向けORMsを利用します。
ORMsとは簡単に言ってしまうとデータベースを操作する際に、SQLを用いて低水準で操作する代わりにオブジェクト指向の言語を用いて高水準での操作を行うための技法です。
技法というとすごくテクニカルなものを想像してしまいますが、まぁPython(Flask)でデータベースを操作できるようにする方法、くらいの認識でまずは良いと思います。
※少なくとも僕はこれ以上の説明はできません。
まずはpipなどでモジュールをインストールし、configの設定を行います。
pip install flask-sqlalchemy
from flask_sqlalchemy import SQLAlchemy
# 中略
app.config['SQLALCHEMY_DATABASE_URI'] = postgresql://flasker@localhost/flaskdb
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
SQLALCHEMY_DATABASE_URIはその名の通り、利用するDBを一意に特定するための情報です。
PostgreSQLの場合は
postgresql://[ユーザー名]:[パスワード]@[ホスト名]/[データベース名]
となります。ちなみにMySQLやSQLiteの場合は
mysql://[ユーザー名]:[パスワード]@[ホスト名]/[データベース名]
sqlite:////absolute/path/to/database # Linux, maxOS
sqlite:///c:/absolute/path/to/database # Windows
となります。
コード例は特にパスワードを設定していないロールなので省略しています。
また'SQLALCHEMY_TRACK_MODIFICATIONS'はデバック時やテスト時に利用するもので、公式ドキュメントでは普段はメモリ削減のためにFalseにすることが奨励されています。
configの設定を終えたらSQLAlchemyクラスの引数にappを加えてdbオブジェクトを作成します。
テーブルの定義
次にテーブルの定義を行います。Flask-SQLAlchemyではモデルと呼ばれるテーブルの名前を含むテーブル構成に関連する情報のことです。
Flask-SQLAlchemyではテーブル構成をクラスで定義し、それをモデルと呼び、そのモデルのインスタンスを作成することでレコードの値を作成します。
実際のモデルは
class Role(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(64), unique = True)
users = db.relationship('User', backref = 'role', lazy = 'dynamic')
def __repr__(self):
return '<Role %r>' % self.name
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key = True)
username = db.Column(db.String(64), unique = True, index = True)
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
def __repr__(self):
return '<User %r>' % self.username
のように定義します。
モデルはdb.Model
を継承する形で作成し、各クラス変数はテーブルの各カラムと対応、__tablename__
はテーブル名と対応しています。
またdef __repr__(self)
はそのクラスやレコードの簡単な要約を文字列で返してくれるメソッドです。
rolesテーブルの変数users
はusersテーブルとリレーションを張るために定義しています。
なお細かい話ですがlazy = 'dynamic'
の必要性に関しては後編で出てきます。
ここでRole
に含まれているusers = db.relationship()
の部分でUser
に対してリレーションを張っています。
これがあることでテーブルUser
のレコードを作成する際に、テーブルRole
の任意のレコードを指定し、2つのテーブルのレコード同士を紐づけることができます。
またその紐付けがされた際にUser
側のレコードに含まれているrole_id
部分にRole
側で紐づいたレコードのIDが格納されます。これをForeignKeyと呼び、role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
で定義しています。
User
側ではForeignKeyを見れば対応するRole
側のレコードが、Role
側では.users
を見れば対応するUser
側のレコードがわかります。
これでテーブルの定義が完了したので、次回はテーブルの作成からクエリの送信を見ていきます。