本文へスキップ
hdknr blog
戻る

Claude Code で Laravel→Django 全自動移行をやってみた(1/3)計画編

業務管理システム(PHP/Laravel 6.20)を Python/Django 4.2 に移行するプロジェクトを、Claude Code の自律実行でほぼ全自動で完遂しました。

本記事は 3 部構成です。

  1. 計画編(本記事)— なぜやったか、どう計画したか
  2. 自動化基盤編 — Claude Code を自律実行させるフレームワークの設計
  3. 実行結果・教訓編 — 実際に何が起きたか、次回への教訓

プロジェクトの背景

移行対象は、ある業種特化の業務管理システムです。契約管理・マスタ管理・CSV インポート・Excel エクスポート・月次締処理・外部サービス連携(OAuth2 / REST / GraphQL)など、典型的な業務アプリの機能を一通り備えています。

Laravel 側のコードベースの規模感:

「手で移行したら何人月かかるか」を考えたとき、Claude Code に全部やらせてみよう、という実験的な発想でプロジェクトが始まりました。


移行方針の決定

1. 既存 DB をそのまま使う(inspectdb 方式)

最も重要な設計判断は、既存の本番 DB ダンプをそのまま使い、Django の inspectdb でモデル雛形を自動生成する方式を採用したことです。

既存 DB ダンプ取得 → Docker MySQL にリストア → inspectdb でモデル生成
→ managed = True に変更 → migrate --fake で初回適用

これにより:

当初は「Laravel のモデル定義を読んで手動で Django モデルを書く」方針でしたが、ユーザー(自分)の「それで大丈夫か?」という問いかけで方針転換しました。ユーザーの素朴な疑問がアーキテクチャ改善に繋がった好例です。

2. 外部 API の事前動作確認

Laravel のコードに書かれている API エンドポイントと、実際に動く API が一致しているとは限りません。準備段階で実際に curl で叩いて確認したところ、いくつかの重要な差異が見つかりました:

これらの差異を事前に CLAUDE.md(Claude Code が読むプロジェクト設定ファイル)に記録したことで、全フェーズを通じて同じ間違いを繰り返さずに済みました。

3. フロントエンドは「コピー&ペースト」

Laravel 側で使っていた UI テーマ(jQuery + Bootstrap ベース)の CSS/JS をそのまま Django の static/ にコピーする方針を取りました。カスタム SASS/JS ビルドは不要 — プリビルドファイルをそのまま使います。

Django テンプレートでは {% load static %} で参照するだけ。フロントエンドのビルドパイプラインを移行する必要がないため、バックエンドのビジネスロジック移行に集中できました。


フェーズ設計

移行作業を 8 フェーズ・15 の GitHub Issue に分割しました。各 Issue に依存関係を定義し、順序通りに自動実行する設計です。

Phase 0: 初期セットアップ(Docker + Django プロジェクト)

Phase 1: モデル定義
  ├── 1-1: マスタ系 10 モデル
  ├── 1-2: 契約系 4 モデル
  └── 1-3: 入金・会計系モデル

Phase 2: 認証 & 外部 API 連携

Phase 3: テンプレート & CRUD
  ├── 3-1: 共通レイアウト + 静的ファイル
  └── 3-2: マスタ管理画面(9 種 × CRUD)

Phase 4: 契約管理
  ├── 4-1: 一覧・検索(28 フィールドフィルタ)
  ├── 4-2: 登録・編集・削除(3 ステップフォーム)
  └── 4-3: 支払更新・番号修正・入金管理

Phase 5: データ入出力
  ├── 5-1: CSV インポート(3 種)
  └── 5-2: Excel エクスポート(4 種)

Phase 6: 月次締処理 & ダッシュボード

Phase 7: テスト & 品質保証

Phase 8: 本番デプロイ準備

技術スタック対応表

項目Laravel(移行元)Django(移行先)
言語PHP 8.0Python 3.11+
フレームワークLaravel 6.20Django 4.2 LTS
ORMEloquentDjango ORM
テンプレートBladeDjango Templates
フォームForm RequestDjango Forms
Excel 処理Maatwebsite Excelopenpyxl
HTTP クライアントGuzzlehttpx
テストPHPUnitpytest-django
パッケージ管理Composer / npmuv
コンテナPHP-FPM + NginxGunicorn + Nginx

CLAUDE.md — Claude Code への「設計書」

Claude Code はプロジェクトルートの CLAUDE.md を自動的に読み込み、プロジェクト固有のルールとして従います。ここに移行プロジェクト特有の情報を集約しました:

# 記載した内容の例

## DB 移行方針
- inspectdb で雛形生成、managed = True に変更
- テーブル名の typo もそのまま使用

## 設計方針
- 認証: 実際の OAuth2 フローをそのまま実装(モック不要)
- フロントエンド: 既存テーマの CSS/JS をそのまま使用
- 外部 API: ハイブリッド構成(DB キャッシュ + API クライアント)

## GraphQL クエリ名の注意
- 顧客: customer_set(Laravel コードの customers は誤り)
- フィールド: company_code(branch_code は存在しない)

## 禁止事項
- git branch / checkout / switch を実行しない
- git push を実行しない
- gh pr create / merge を実行しない

特に重要だったのは 「やってはいけないこと」の明示 です。Claude Code は指示がなければ自律判断しますが、禁止事項がないと予期しない操作(ブランチ切替、main への直接 push 等)を行うことがあります。これは実行結果・教訓編で紹介する「ブランチ分岐問題」の原因にもなりました。


品質保証の設計

自律実行では人間のコードレビューが介在しないため、品質保証の仕組みを多層的に設計しました。

1. Pre-commit Hook

# コミット前に自動実行
uv run ruff format <staged files>
uv run ruff check --fix <staged files>

2. PostToolUse Hook(Claude Code 固有)

Claude Code がファイルを編集するたびに ruff check を自動実行。構文エラーやスタイル違反を即座にフィードバックします。

3. GitHub Actions CI

push/PR → ruff format + ruff check → Django check → pytest

4. verify-phase.sh

各フェーズ完了後に実行する検証スクリプト:

5. code-reviewer サブエージェント

Claude Code 内部で別の Claude インスタンスをコードレビュアーとして起動し、セキュリティ問題やロジックエラーを検出します。実際に GraphQL インジェクション、XSS、URL エンコード漏れなどを検出・修正できました。


次回予告

計画編では「何を、なぜ、どう設計したか」を紹介しました。

次の自動化基盤編では、この計画を実際に自律実行するためのフレームワーク — run-issue.sh の設計と、Claude Code をどう制御するかを解説します。



前の記事
Dexter: 約200行で動く自律型金融リサーチエージェント
次の記事
Claude Code で Laravel→Django 全自動移行をやってみた(3/3)実行結果・教訓編