DjangoでSQLAlchemyを使ってみよう
Django ORM の問題点
実のところ、Django ORMはデータベース操作には適していません。基本的なCRUD操作のみを実行しているときは問題ないように見えるのですが、N+1問題 として知られているような、最適化されていない方法でデータベースクエリを実行することになり、アプリケーションの性能に影響を与えることがあります。 また、Django ORMにはいつくかの重要なSQL機能をサポートしていないため、Django ORM では表現できないこともあり、結局SQLクエリに戻ることになってしまいます。
SQLクエリをハードコーディングしてしまうと、ORMを使っている意味が薄れてしまうだけでなく、その保守も簡単ではなくなってしまいます。
Django でSQLAlchemyを使う
Pythonには他にも多くのORMがあります。次のものは代表的なものです。
Peewee:とても美しい実装なのですが、サポートするデータベースが少ない Tortoise:非同期I/OをサポートするORM。Django ORM に触発されて開発された。 人気も高く多機能でデータベースのサポートが多いSQLAlchemy を使うことにしましょう。
しかし、Django で SQLAlchemy を使うときにも問題点があります。
それは、SQLAlchemy とDjango ORM とには互換性がないことと、Django はORMを置き換えることを想定して設計されていないため、SQLAlchemyのデータ構造を別に記述する必要があり冗長になってしまうということです。
Django + Aldjemy
Aldjemy は既存のDjangoプロジェクトにSQLAlchemyを組み込むためのパッケージです
Django ORMでは不可能な複雑なクエリも、Aldjemy を使うと簡単に実現できます。
https://gyazo.com/8ccaaba108da7fd469497a708b325b26
INSTALLED_APPSの最後にaldjemyを追加しておく必要があります。
モデルがインポートされると、aldjemyはすべてのモデルを読み取り、saアトリビュートをモデルに提供します。 saアトリビュートは、Tableクラスにマップされるクラスです。
aldjemyはDjangoモデルからテーブルを生成します。 これは、SQLAlchemyリフレクションを使用する標準的な方法との決定的で重要な違いです。これにより、aldjemy はほぼすべての
クエリをSQLに変換することができます。
コード例:
code: Python
User.sa.query().filter(User.sa.username=='Brubeck')
多対多リレーションシップの例:
code: Python
User.sa.query().join(User.sa.groups).filter(Group.sa.name=="GROUP_NAME")
リフレクション(Reflection)
リフレクション は、プログラムの実行過程でプログラム自身の構造を読み取ったり、
書き換えたりする技術のこと。
データベース領域おいては、実行過程でデータベースのフィールドやオブジェクトを読み取ること。
インストールと準備
拡張モジュールなので次のようにインストールします。
code: bash
$ pip install aldjemy
プロジェクトのsettings.py にある INSTALLED_APPS の最後にaldjemy を追加します。
code: Python
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_extensions',
'aldjemy',
]
Aldjemy の使い方
code: Python
In 1: User.sa.query().filter(User.sa.username=='freddie') Out1: <sqlalchemy.orm.query.Query at 0x111672a20> Django ORM の中からsaアトリビュートを経由して SQLAlchemy を呼び出すことができるようになります。
いま、myapp.models というモジュールがあり、3つのDjangoモデル(Blog, Author, Entry)が定義されているとします。次のようにすると、aldjemy を意識せずにSQLAlchemyモデルとして使用できるようになります。
code: Python
Blog = myapp.models.Blog.sa
Author = myapp.models.Author.sa
Entry = myapp.models.Entry.sa
SQLAlchemyのセッションオブジェクトにアクセスするために、次の関数を定義します。
code: Python
def Session():
from aldjemy.core import get_engine
engine = get_engine()
_Session = sessionmaker(bind=engine)
return _Session()
あとは、これを呼び出して返されるオブジェクトを使うだけです。
code: Python
session = Session()
参考: