d2a に autoload 機能を追加しました

2019-02-22

前に作ったライブラリとして 【Djangoから】変換ライブラリ d2a のご紹介【SQLAlchemyへ】 の紹介をしましたが、更新して結構便利になったので再び紹介しておこうと思います。

インストールは以前と同様に pip で pip install d2a (すでにインストールされてる場合は更新するために -U をつけます)

前は models.py と同じディレクトリに models_sqla.py みたいなモジュールを置いて、 以下のように書いておくことで、モデルをもとに SQLAlchemy のモデルを自動生成してくれるというものでした。

from d2a import transfer
from . import models
transfer(models, globals())

この機能自体は今も健在ですが、すべてのアプリに配置するのは少々めんどくさいですね。

そこで自動的にすべての アプリに このモジュールを配置する機能を追加しました。

やりかたは簡単で Django の settings.INSTALLED_APPS'd2a' を追加するだけです。

例)

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # 追加する位置は 先頭かアプリの前
    'd2a',

    # アプリ
    'books',
    'sales',
]

警告

INSTALLED_APPS 内の 'd2a' は 自作アプリの前におくことを推奨します

理由は apps.py から d2a で作成した alchemy モデルを参照しようとしても 存在せずエラーになってしまうためです。

現状参照していなくても 参照関係が変わればエラーになる可能性があるので、 先に読み込んでおくに越したことはありません。

モジュールを配置するとは言いましたが、物理的にPythonファイルができるわけではなく インポート可能なモジュールオブジェクトを インメモリに持つだけです。

これだけで models と同じように models_sqla をインポートできるようになり、 その中には モデルと同名の SQLAlchemy ORM オブジェクト (もしくは Expression オブジェクト) が入っています。

from books import models_sqla

備考

models_sqla というモジュール名は 設定で変えられます

また、カスタマイズしたフィールドを使っている場合は alias 関数で 別名を定義してあげましたが、これも含め settings に書けるようにしました。

D2A_CONFIG という 変数を辞書で定義します。これは必須ではありません。

例)

D2A_CONFIG = {
    'AUTOLOAD': {
        # 自動生成するモジュール名を変えたい場合に指定する
        'module': 'modelsa',
        'option': {
            # ORM じゃなくて Expression オブジェクトが欲しい場合は True にする
            'as_table': True,
        }
    },
    #
    'ALIASES': {
        # ImageField を継承したフィールドなら ImageField に変換する場合は以下のように指定すればいい
        CustomImageField: ImageField,
    },
}

もちろん alias でもできます。

個人的にはフィールドクラス定義直後に alias で登録するのがおすすめです。

from d2a import alias, alias_dict
from django.db.models import ImageField


class CustomImageField(ImageField):
    pass


alias(CustomImageField, ImageField)
# もしくは以下(複数あるときはこっちのほうがいいかも
alias_dict({
  CustomImageField: ImageField,
})

スター待っとるやで〜 righ/d2a (2回目)