この記事は最終更新日から1年以上が経過しています。
WIZY の開発では、Python + MySQLの構成でORマッパーに SQLAlchemy を使用しています。
SQLAlchemyは高機能なのですがまとまったドキュメントがなく、また「どのようにコードを記述したらどのようなクエリが発行されるのか」というのはDB設計やユースケースがサンプルとは異なるので、運良くマッチした情報が出て来ない限り自分でクエリ(を生成するコード)を組み立てる必要があります。
パターン1) loggingでログに出力する
SQLAlchemyを利用しているアプリケーションで以下のコードを記述することでクエリをログに出力することができます。
import logging logging.basicConfig() logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO) |
パターン2) mysql用にクエリをコンパイル
パターン1はクエリに渡した変数が出力されない問題があります。
変数を含むクエリ全体を確認したい場合はクエリをコンパイルして確認する方法が使えます。
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String from sqlalchemy.orm import sessionmaker from sqlalchemy.dialects import mysql class MyTable(declarative_base()): __tablename__ = 'my_table' id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(255, collation='utf8_unicode_ci'), default=None) if __name__ == '__main__': Session = sessionmaker() query = Session().query(MyTable).filter(MyTable.id == 10) print(query.statement.compile(dialect=mysql.dialect(), compile_kwargs={"literal_binds": True})) |
実行結果
SELECT my_table.id, my_table.name FROM my_table WHERE my_table.id = 10 |
コンパイルに渡している
dialect でMySQLの文法で変換すること、
compile_kwargs={"literal_binds": True} で変数をセットした状態で表示することを示しています。
Flask-SQLAlchemyを使用した場合
WebフレームワークFlaskとSQLAlchemyを利用する場合はFlask-SQLAlchemyが利用できます。
この場合に同じことをするには、Flask-Scriptも使用して以下のようになります。
from flask import Flask from flask_script import Manager from flask_sqlalchemy import SQLAlchemy from sqlalchemy.dialects import mysql app = Flask(__name__) app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True db = SQLAlchemy() db.init_app(app) manager = Manager(app) class MyTable(db.Model): __tablename__ = 'my_table' id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String(255, collation='utf8_unicode_ci'), default=None) @manager.command def main(): query = db.session.query(MyTable).filter(MyTable.id == 10) print(query.statement.compile(dialect=mysql.dialect(), compile_kwargs={"literal_binds": True})) if __name__ == '__main__': manager.run() |
実行結果
$ python hoge.py main SELECT my_table.id, my_table.name FROM my_table WHERE my_table.id = 10 |
まとめ
ORマッパーを使用していても複雑な条件を利用したい場合は実際に出力されるSQLを確認しながら開発を進めることで、予想外の動きやケース漏れを防ぐことができると思います。
この記事を書いた人
最近書いた記事
- 2021.12.10React NativeでWallet風UIを実装する
- 2018.11.19Elasticsearchで簡単な検索とscoreを調整する方法
- 2018.10.05ECSをEC2からFargateに切り替える際の注意点
- 2018.09.12AKB48グループ映像倉庫のWeb版をリリースしました