1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

FlaskアプリのDBをFlask-SQLAlchemyで構築する(前編)

Last updated at Posted at 2021-05-22

どうも、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側のレコードがわかります。

これでテーブルの定義が完了したので、次回はテーブルの作成からクエリの送信を見ていきます。

1
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
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?