既存サービスのリプレイス案件で、管理画面一式を Django 以外のフレームワークで
再現する必要が出ました。Django admin の便利さを痛感した仕事でした。
Django admin が実際にやってくれていること
移植して初めて分かりますが、admin は次を全部やっています。
- モデル定義からのフォーム自動生成とバリデーション
- 一覧の検索・絞り込み・並び替え・ページング
- 権限(モデル単位・オブジェクト単位)
- 変更履歴(誰が・いつ・何を)
- 外部キーの選択UI(オートコンプリート含む)
これを手で書くと、素直に作れば数か月かかります。
全部は作らない、と決める
最初にやったのは機能の棚卸しでした。実際の管理画面の利用ログを見ると、
使われている画面は全体の3割程度でした。
- 毎日使う画面 … 作り込む
- 月1回の画面 … 最低限のCRUDだけ
- 1年間アクセスなし … 作らない(必要になったら追加)
「Django admin と同じものを作る」ではなく
「実際に使われている操作を作る」に目標を置き換えたのが最大の判断でした。
共通化した3つの部品
1. 一覧のクエリ生成
検索・絞り込み・並び替え・ページングは、どの画面でも同じ構造です。
宣言的に書けるようにしました。
LIST_CONFIG = {
"users": {
"search": ["name", "email"],
"filters": ["status", "plan"],
"order": ["-created_at"],
},
}
2. フォームの自動生成
モデルのカラム定義から入力欄を組み立てます。
型ごとのウィジェットと必須チェックだけでも、手書きの量が激減しました。
3. 監査ログ
これは最初から必須にしました。
誰が・いつ・どのレコードを・どう変えたかを全操作で残します。
def log_change(user, obj, action, before, after):
AuditLog.objects.create(
user=user, model=obj.__class__.__name__, object_id=obj.pk,
action=action, diff=json_diff(before, after),
)
管理画面は権限の強い人が触るので、ここが無いと事故の追跡ができません。
複数DBを跨ぐときの注意
参照系が複数DBに分かれている構成では、トランザクションが跨げません。
「片方だけ書き込まれた」状態が普通に起こります。
対処は2つでした。
- 書き込みは可能な限り1つのDBに寄せる
- どうしても跨ぐ場合は、後から突合できるように相関IDを持たせる
分散トランザクションを自前で作るのは、規模に対して割に合いませんでした。
開発環境をローカルで完結させる
AWS 依存のまま開発すると、全員が同じクラウド環境を共有して事故ります。
ローカルでエミュレートできる仕組みを入れ、
開発者が1コマンドで環境を立ち上げられる状態にしました。
これは移植そのものより、チームの速度に効きました。
まとめ
- admin 相当を全部は作らない。使われている画面を実測して決める
- 一覧・フォーム・監査ログの3つを共通部品にすると量が激減する
- 複数DBを跨ぐトランザクションは諦め、寄せるか突合できるようにする
- ローカルで完結する開発環境が、移植作業そのものより効く