「SQLインジェクションを対策したい」
「PythonでPostgreSQLのORM操作を行いたい」
このような場合には、この記事の内容が参考になります。
この記事では、PythonでPostgreSQLをORM操作する方法を解説しています。
本記事の内容
- SQLAlchemyによるPostgreSQLのORM操作
- 動作確認のための準備
- psycopg2によるデータ取得
- SQLAlchemy(psycopg2を内部で利用)によるデータ取得
それでは、上記に沿って解説していきます。
SQLAlchemyによるPostgreSQLのORM操作
SQLAlchemyは、PythonでデータベースをORM操作する際の選択肢となります。
ただし、SQLAlchemyはあくまでORMライブラリに過ぎません。
SQLAlchemyのインストールについては、次の記事で説明しています。
データベースへの接続には、ドライバーを利用します。
今回であれば、対象データベースがPostgreSQLになります。
PostgreSQLのインストールについては、以下の記事で説明しています。
PostgreSQLのドライバーと言えば、psycopg2の名前が真っ先に出てきます。
PythonにおけるPostgreSQLのドライバーとしては、psycopg2が最も利用されているでしょう。
これらを用いて、SQLAlchemyによるPostgreSQLのORM操作が可能となります。
そのため、次の2つをインストールする必要があります。
- SQLAlchemy
- psycopg2
以上、SQLAlchemyによるPostgreSQLのORM操作について説明しました。
次は、動作確認のための準備を説明します。
動作確認のための準備
PostgreSQLには、サンプルデータベースが用意されています。
このサンプルデータベースを用いて、動作確認を行います。
具体的には、次のテーブルからデータを取得する動作を確認します。

データ件数は、全部で16件です。
dvdrental=# select * from category;
category_id | name | last_update
-------------+-------------+---------------------
1 | Action | 2006-02-15 09:46:27
2 | Animation | 2006-02-15 09:46:27
3 | Children | 2006-02-15 09:46:27
4 | Classics | 2006-02-15 09:46:27
5 | Comedy | 2006-02-15 09:46:27
6 | Documentary | 2006-02-15 09:46:27
7 | Drama | 2006-02-15 09:46:27
8 | Family | 2006-02-15 09:46:27
9 | Foreign | 2006-02-15 09:46:27
10 | Games | 2006-02-15 09:46:27
11 | Horror | 2006-02-15 09:46:27
12 | Music | 2006-02-15 09:46:27
13 | New | 2006-02-15 09:46:27
14 | Sci-Fi | 2006-02-15 09:46:27
15 | Sports | 2006-02-15 09:46:27
16 | Travel | 2006-02-15 09:46:27
(16 rows)
あと、PythonからPostgreSQLにアクセスするユーザーを用意する必要があります。
上記記事に従えば、ユーザーpostgresでサンプルデータベースを作成しているはずです。
postgresで作成している場合は、postgresのパスワードを設定しておきましょう。
postgresには、パスワード未設定の場合がありえます。
その場合は、Pythonからアクセスできません(パスワードを求められる)。
パスワードの設定には、次のクエリを実行します。
ただし、ユーザーpostgresでアクセスした状態である必要があります。
ALTER USER postgres WITH PASSWORD 'postgres';
プロンプト表示が「postgres=#」であれば、ユーザーpostgresでアクセスした状態です。
postgres=# ALTER USER postgres WITH PASSWORD 'postgres';
以上、動作確認のための準備を説明しました。
次は、psycopg2によるデータ取得を説明します。
psycopg2によるデータ取得
まずは、psycopg2によるデータ取得を確認します。
各自で必要な箇所は、変更してください。
import psycopg2
DATABASE = 'postgresql'
USER = 'postgres'
PASSWORD = 'postgres'
HOST = 'localhost'
PORT = '5432'
DB_NAME = 'dvdrental'
CONNECT_STR = '{}://{}:{}@{}:{}/{}'.format(DATABASE, USER, PASSWORD, HOST, PORT, DB_NAME)
conn = psycopg2.connect(CONNECT_STR)
cur = conn.cursor()
cur.execute('SELECT category_id, name FROM category ORDER BY category_id LIMIT 3')
rows = cur.fetchall()
for target in rows:
print(target[0], target[1])
cur.close()
conn.close()
昇順にソートして、上位3件をSELECTするSQL文を実行しています。
上記コードを実行した結果は、以下。
1 Action 2 Animation 3 Children
想定通りの動きをしています。
以上、psycopg2によるデータ取得を説明しました。
次は、SQLAlchemy(psycopg2を内部で利用)によるデータ取得を説明します。
SQLAlchemy(psycopg2を内部で利用)によるデータ取得
SQLAlchemyによるORM操作の場合は、次のコードを用います。
こちらも設定は、各自の環境に合わせてください。
import sqlalchemy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import sessionmaker
DATABASE = 'postgresql'
USER = 'postgres'
PASSWORD = 'postgres'
HOST = 'localhost'
PORT = '5432'
DB_NAME = 'dvdrental'
CONNECT_STR = '{}://{}:{}@{}:{}/{}'.format(DATABASE, USER, PASSWORD, HOST, PORT, DB_NAME)
Base = declarative_base()
class Category(Base):
category_id = Column(Integer, primary_key=True)
name = Column(String(length=25))
__tablename__ = 'category'
engine = sqlalchemy.create_engine(CONNECT_STR, echo=False)
session = sessionmaker(bind=engine)()
query_result = session.query(Category).order_by(Category.category_id).limit(3)
for target in query_result:
print(target.category_id, target.name)
Categoryクラスは、categoryテーブルをもとに作成しています。
データ取得は、次のコードで実現。
query_result = session.query(Category).order_by(Category.category_id).limit(3)
全データ取得は、次のコードで表現できます。
query_result = session.query(Category)
今回は、昇順に上位3件を取得します。
そのため、以下をコードに追記する形となります。
| 昇順にソート | order_by(Category.category_id) |
| 上位3件 | limit(3) |
上記コードを実行した結果は、以下。
1 Action 2 Animation 3 Children
psycopg2のみで取得した結果と同じです。
ORM操作では、SQL文を記載していません。
しかし、裏では同じSELECT文が実行されているはずです。
それを確認したい場合は、次のコードを変更します。
engine = sqlalchemy.create_engine(CONNECT_STR, echo=False)
↓↓↓
engine = sqlalchemy.create_engine(CONNECT_STR, echo=True)
変更して実行すると、以下の結果となります。
2022-07-09 13:31:40,066 INFO sqlalchemy.engine.Engine select pg_catalog.version()
2022-07-09 13:31:40,066 INFO sqlalchemy.engine.Engine [raw sql] {}
2022-07-09 13:31:40,069 INFO sqlalchemy.engine.Engine select current_schema()
2022-07-09 13:31:40,069 INFO sqlalchemy.engine.Engine [raw sql] {}
2022-07-09 13:31:40,069 INFO sqlalchemy.engine.Engine show standard_conforming_strings
2022-07-09 13:31:40,069 INFO sqlalchemy.engine.Engine [raw sql] {}
2022-07-09 13:31:40,070 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2022-07-09 13:31:40,073 INFO sqlalchemy.engine.Engine SELECT category.category_id AS category_category_id, category.name AS category_name
FROM category ORDER BY category.category_id
LIMIT %(param_1)s
2022-07-09 13:31:40,074 INFO sqlalchemy.engine.Engine [generated in 0.00024s] {'param_1': 3}
1 Action
2 Animation
3 Children
結果から、実行するクエリを確認できますね。
以上、SQLAlchemy(psycopg2を内部で利用)によるデータ取得を説明しました。





