Flaskでデータベースを操作する(Flask-SQLAlchemy)

プログラミング

Flask-SQLAlchemyによるデータベース操作:実践と応用

Flask-SQLAlchemyは、PythonのWebフレームワークであるFlaskと、SQLAlchemy ORM(Object-Relational Mapper)を連携させるための拡張機能です。これにより、Pythonオブジェクトを介してリレーショナルデータベース(RDB)を直感的に操作できるようになります。SQLAlchemyの強力な機能とFlaskのシンプルさを組み合わせることで、Webアプリケーションにおけるデータ管理を効率的かつ安全に行うことができます。

インストールと初期設定

Flask-SQLAlchemyを導入するには、まずpipコマンドを使用してインストールします。

“`bash
pip install Flask-SQLAlchemy
“`

次に、Flaskアプリケーション内でFlask-SQLAlchemyを初期化します。Flaskアプリケーションのインスタンスを作成した後、SQLAlchemyオブジェクトを初期化し、データベースURIを設定します。

“`python
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config[‘SQLALCHEMY_DATABASE_URI’] = ‘sqlite:///database.db’ # SQLiteの場合
db = SQLAlchemy(app)
“`

`SQLALCHEMY_DATABASE_URI`は、接続するデータベースの種類と場所を指定する文字列です。SQLite、PostgreSQL、MySQLなど、様々なデータベースに対応しています。SQLiteはファイルベースのため、手軽に試すことができます。

モデルの定義

Flask-SQLAlchemyでは、データベースのテーブルをPythonのクラスとして表現します。これを「モデル」と呼びます。モデルクラスは`db.Model`を継承し、各クラスの属性がテーブルの列に対応します。

“`python
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)

def __repr__(self):
return ” % self.username
“`

* `db.Column`: テーブルの列を定義します。
* `db.Integer`, `db.String`: 列のデータ型を指定します。
* `primary_key=True`: 主キーとして指定します。
* `unique=True`: 列の値が一意であることを保証します。
* `nullable=False`: null値を許可しないことを指定します。

この`User`クラスは、`users`という名前のテーブル(デフォルトではクラス名を小文字にして複数形にしたもの)を作成し、`id`, `username`, `email`という3つの列を持つことを示しています。

データベースの作成とマイグレーション

モデルを定義したら、データベーステーブルを作成する必要があります。Flask-SQLAlchemyは、データベーススキーマの変更を管理するための「マイグレーション」機能も提供します。一般的には、AlembicというライブラリがFlask-Migrateパッケージを通じてFlask-SQLAlchemyと連携して使用されます。

まず、Flask-Migrateをインストールします。

“`bash
pip install Flask-Migrate
“`

そして、アプリケーションにFlask-Migrateを初期化します。

“`python
from flask_migrate import Migrate

migrate = Migrate(app, db)
“`

マイグレーションコマンドを使用するには、`flask`コマンドラインインターフェースが必要です。

“`bash
# マイグレーションリポジトリの初期化
flask db init

# マイグレーションスクリプトの生成
flask db migrate -m “Initial migration”

# データベースへの適用
flask db upgrade
“`

`flask db init`は、`migrations`というディレクトリを作成し、Alembicの設定ファイルなどを配置します。`flask db migrate`は、モデルの変更を検出して、データベーススキーマの変更を記述したマイグレーションスクリプトを`migrations/versions`ディレクトリに生成します。`flask db upgrade`は、生成されたマイグレーションスクリプトを実行し、データベーススキーマを更新します。

データの追加、取得、更新、削除(CRUD操作)

Flask-SQLAlchemyを使用すると、CRUD(Create, Read, Update, Delete)操作をPythonオブジェクトとして容易に実行できます。

データの追加(Create)

新しいレコードを追加するには、モデルクラスのインスタンスを作成し、`db.session.add()`メソッドでセッションに追加し、`db.session.commit()`でコミットします。

“`python
new_user = User(username=’alice’, email=’alice@example.com’)
db.session.add(new_user)
db.session.commit()
“`

データの取得(Read)

レコードを取得するには、`User.query`オブジェクトを使用します。

* **全件取得**: `User.query.all()`
* **条件指定**: `User.query.filter_by(username=’alice’).first()`
* **IDで取得**: `User.query.get(1)`

“`python
all_users = User.query.all()
alice = User.query.filter_by(username=’alice’).first()
user_1 = User.query.get(1)
“`

データの更新(Update)

既存のレコードを取得し、その属性を変更した後、`db.session.commit()`を呼び出すことで更新できます。

“`python
user_to_update = User.query.filter_by(username=’alice’).first()
if user_to_update:
user_to_update.email = ‘alice.updated@example.com’
db.session.commit()
“`

データの削除(Delete)

削除したいレコードを取得し、`db.session.delete()`メソッドでセッションから削除し、`db.session.commit()`でコミットします。

“`python
user_to_delete = User.query.filter_by(username=’alice’).first()
if user_to_delete:
db.session.delete(user_to_delete)
db.session.commit()
“`

リレーションシップの定義

データベースでは、テーブル間の関連性を定義することが一般的です。Flask-SQLAlchemyは、SQLAlchemyの強力なリレーションシップ機能を提供します。

* **一対多 (One-to-Many)**: 例えば、一人のユーザーが複数の投稿を持つ場合。
* **多対一 (Many-to-One)**: 例えば、複数のコメントが一人(または一つの記事)に関連付けられる場合。
* **多対多 (Many-to-Many)**: 例えば、複数のユーザーが複数のグループに所属する場合。

例として、Userモデルと、各Userが持つ複数のPostモデル(仮定)を定義してみましょう。

“`python
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey(‘user.id’), nullable=False) # Userテーブルのidを参照

# Userモデルとのリレーションシップを定義
user = db.relationship(‘User’, backref=db.backref(‘posts’, lazy=True))
“`

この例では、`Post`テーブルに`user_id`という外部キー(`user`テーブルの`id`を参照)を設けています。`db.relationship(‘User’, backref=db.backref(‘posts’, lazy=True))`は、`Post`モデルから`User`モデルへのリレーションシップを定義し、さらに`User`モデルから`posts`という名前で逆方向のリレーションシップ(そのユーザーが作成した投稿のリスト)を定義しています。`lazy=True`は、投稿が必要になったときに初めてロードされることを意味します。

これにより、以下のような操作が可能になります。

“`python
# 特定のユーザーの投稿を取得
user_alice = User.query.filter_by(username=’alice’).first()
if user_alice:
for post in user_alice.posts:
print(post.title)

# 特定の投稿の作成者を取得
post_1 = Post.query.get(1)
if post_1:
print(post_1.user.username)
“`

クエリの高度な使い方

SQLAlchemyのクエリインターフェースは非常に強力で、様々な条件でデータを絞り込んだり、ソートしたり、集計したりすることができます。

* **ORDER BY**: `User.query.order_by(User.username.desc())`
* **LIMIT / OFFSET**: `User.query.limit(10).offset(20)`
* **GROUP BY / HAVING**: `db.session.query(func.count(User.id), User.username).group_by(User.username).all()` (この場合、`from sqlalchemy import func`が必要です)
* **JOIN**: リレーションシップが定義されていれば、自動的にJOINが行われることもありますが、明示的にJOINを指定することも可能です。

### まとめ

Flask-SQLAlchemyは、Flaskアプリケーションでデータベースを扱うための標準的かつ強力なツールです。SQLAlchemyのORM機能とFlaskのWebフレームワークとしての利便性を組み合わせることで、開発者はデータベースの複雑さから解放され、ビジネスロジックの実装に集中できます。モデル定義、CRUD操作、リレーションシップ、そして高度なクエリ機能といった一連の機能は、小規模なプロジェクトから大規模なアプリケーションまで、幅広いニーズに対応します。データベーススキーマの管理にはFlask-Migrateを利用することで、変更履歴を追跡し、安全なデプロイメントを実現できます。これらの機能を理解し、適切に活用することで、堅牢でスケーラブルなWebアプリケーションを効率的に開発することが可能になります。