Pythonアプリケーションで手軽にデータベースを扱いたいとき、ORM(Object Relational Mapper)を使うとSQLを直接書かずにPythonのクラス操作でデータ操作ができます。
本記事では、軽量ORMライブラリの Peewee を初心者向けにゼロから解説します。
Peeweeとは?
Peewee(ピューウィー)は、SQLite・MySQL・PostgreSQLなど複数のデータベースに対応した軽量ORMライブラリです。
特徴
- インストールが簡単
- 設定がシンプル
- 少ないコードでモデル操作が可能
- 中規模プロジェクトまで十分な機能を持つ
Python標準ライブラリのsqlite3モジュールよりも直感的にテーブル操作ができ、Django ORMほど重くないため、小〜中規模プロジェクトに適しています。
環境構築と設定
インストール
pip install peewee
SQLiteを利用する場合は追加のドライバ不要ですが、MySQLやPostgreSQLを使う場合はそれぞれ pymysql や psycopg2 をインストールします。
pip install pymysql # MySQL用ドライバ
pip install psycopg2-binary # PostgreSQL用ドライバ
データベース接続設定
from peewee import SqliteDatabase
# SQLiteの場合
db = SqliteDatabase('my_database.db')
# MySQLの場合
# from peewee import MySQLDatabase
# db = MySQLDatabase('my_db', user='user', password='pass', host='localhost', port=3306)
# PostgreSQLの場合
# from peewee import PostgresqlDatabase
# db = PostgresqlDatabase('my_db', user='user', password='pass', host='localhost', port=5432)
データベースオブジェクト db を用いて、モデル定義や接続処理を行います。
モデルの定義
PeeweeではテーブルをPythonクラスとして定義します。まずは簡単な「ユーザー」テーブルの例を見てみましょう。
from peewee import Model, CharField, IntegerField
class BaseModel(Model):
class Meta:
database = db # 先ほど定義したデータベースを指定
class User(BaseModel):
username = CharField(unique=True)
age = IntegerField()
# テーブルを作成
db.connect()
db.create_tables([User])
- Model を継承し、各フィールドを CharField, IntegerField などで定義
- Meta.database でどのDBを使うか指定
- create_tables() で実際にテーブルを作成
基本的なCRUD操作
Create(作成)
# レコードの作成
user = User.create(username='alice', age=30)
Read(読み取り)
# 全件取得
for u in User.select():
print(u.username, u.age)
# 条件付き取得
alice = User.get(User.username == 'alice')
print(alice.age)
Update(更新)
# 30歳→31歳に更新
alice.age = 31
alice.save()
# またはクエリで直接更新
User.update(age=32).where(User.username == 'alice').execute()
Delete(削除)
# レコード削除
alice.delete_instance()
# 条件付き削除
User.delete().where(User.age < 18).execute()
リレーションの扱い方
1対多(ForeignKeyField)
投稿とユーザーの1対多関係を例にしてみます。
from peewee import ForeignKeyField, TextField
class Post(BaseModel):
user = ForeignKeyField(User, backref='posts')
content = TextField()
db.create_tables([Post])
# 投稿作成
post = Post.create(user=alice, content='こんにちは、Peewee!')
# ユーザーが持つ投稿一覧を取得
for p in alice.posts:
print(p.content)
- ForeignKeyField(Model) で外部キーを定義
- backref で逆参照名を指定
多対多
中間テーブルを自分で定義します。
class Tag(BaseModel):
name = CharField(unique=True)
class PostTag(BaseModel):
post = ForeignKeyField(Post)
tag = ForeignKeyField(Tag)
db.create_tables([Tag, PostTag])
# タグ付け
t1 = Tag.create(name='Python')
t2 = Tag.create(name='ORM')
PostTag.create(post=post, tag=t1)
PostTag.create(post=post, tag=t2)
# 特定の投稿のタグ一覧取得
tags = Tag.select().join(PostTag).where(PostTag.post == post)
for t in tags:
print(t.name)
クエリの応用テクニック
フィルタリングとソート
# 年齢が20以上のユーザーを年齢順に取得
users = User.select().where(User.age >= 20).order_by(User.age.desc())
集計
from peewee import fn
# 平均年齢を取得
avg_age = User.select(fn.AVG(User.age)).scalar()
print(f'平均年齢: {avg_age}')
トランザクション
with db.atomic():
# 複数の操作を一括でコミット/ロールバック
u1 = User.create(username='bob', age=25)
u2 = User.create(username='carol', age=28)
まとめ
- Peeweeは軽量で使いやすいORM
- モデル定義からCRUD、リレーション、集計、トランザクションまでカバー
- 小〜中規模のプロジェクトに最適
次章の演習問題で実際に手を動かしながら、学んだことを定着させましょう。
演習問題
- ユーザーモデルに「email」フィールドを追加して、ユニーク制約を設定するSQLをPeeweeで書いてください。
- 「Post」テーブルに「タイトル(title)」フィールドを追加し、タイトルに「Peewee」という文字列が含まれる投稿を取得するクエリを記述してください。
- TagとPostの多対多関係を用いて、投稿ごとにタグの件数を集計し、件数が多い順に並べ替えるクエリを書いてください。
解答例
問1 解答例
from peewee import CharField
class User(BaseModel):
username = CharField(unique=True)
age = IntegerField()
email = CharField(unique=True) # emailフィールドを追加
# マイグレーションが必要な場合は、手動でALTER TABLEを実行するか、peewee-migrateなどを使用
db.create_tables([User])
問2 解答例
from peewee import TextField
# Postモデルにタイトルを追加
class Post(BaseModel):
user = ForeignKeyField(User, backref='posts')
title = CharField() # タイトルフィールド
content = TextField()
# 「Peewee」を含むタイトルを持つ投稿を取得
peewee_posts = Post.select().where(Post.title.contains('Peewee'))
for p in peewee_posts:
print(p.title, p.content)
問3 解答例
from peewee import fn
# タグごとの件数を集計し、投稿ごとに並べ替え
query = (Post
.select(Post, fn.COUNT(PostTag.tag).alias('tag_count'))
.join(PostTag)
.group_by(Post)
.order_by(fn.COUNT(PostTag.tag).desc()))
for p in query:
print(f'投稿ID={p.id}, タグ数={p.tag_count}')
以上で、Peeweeの基本から応用までをカバーする入門ガイドは完了です。演習問題で実際に手を動かし、理解を深めてください。今後の開発に役立つ軽量ORMとして、ぜひPeeweeを活用してみましょう!