dmr-openapi-skeleton について
dmr-openapi-skeletonは、OpenAPI 3.1以降の仕様からdjango-modern-restのトランスポート層を生成する開発スキルです。型付きDTO、コントローラー、ルーター、ドキュメント設定、基本テストを作成し、業務ロジックは原則含めません。
主な機能
- 01OpenAPI仕様の読み取りと分析
- 02型付きDTOとコントローラーの生成
- 03ルーターとドキュメントの配線
- 04基本的なルート・スキーマテスト
- 05生成物と元仕様の差分確認
活用シーン
- 01OpenAPI仕様からDjango APIの骨格を作成
- 02既存プロジェクトにAPIアプリを生成
- 03生成スキーマと公開契約の確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ wemake-services/ django-modern-rest --skill dmr-openapi-skeletonインストール後、Claude Code で/dmr-openapi-skeletonを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
.claude-plugin/plugin.jsonagents/openai.yamlreferences/framework-patterns.mdproject-map.mdspec-fidelity.md詳細
DMR OpenAPI スケルトン
概要
OpenAPI 3.1 以降の仕様から、django-modern-rest 用の実行可能なトランスポート層のスケルトンを生成します。出力は意図的に薄く保ちます。型付き DTO、ベースコントローラー、ルーター、ドキュメントの配線、最小限のテストを生成し、デフォルトではビジネスロジックを一切含めません。
ローカルの信頼できる情報源として、django_test_app/server/apps/* と tests/* のリポジトリ内の例を使用してください。dmr の構成要素を選択する際は references/framework-patterns.md を、生成ファイルの配置先を決める際は references/project-map.md を参照してください。また、元となる OpenAPI ドキュメントが正式な仕様であり、生成したプロジェクトで有用なボイラープレートとして公開契約をできるだけ忠実に保つ必要がある場合は、references/spec-fidelity.md を参照してください。
主なフレームワークのドキュメント:
ワークフロー
まず仕様を読む
- コードを編集する前に、提供された OpenAPI ドキュメントを読みます。
openapiが3.1.x以降であることを確認します。ドキュメントが古い、不明瞭、または不完全な場合は、ファイルを生成する前にその旨を伝えます。- タグ、パスグループ、操作 ID、パラメーター、リクエストボディ、レスポンスコード、再利用可能なスキーマ、セキュリティ宣言を抽出します。
oneOf、anyOf、allOf、識別子、複数のメディアタイプ、コールバック、Webhook セクションなど、扱いの難しい構造を早い段階で検出します。
元の仕様が正式な仕様である場合は、仕様忠実性モードに入る
- ユーザーが既存の OpenAPI ドキュメントを提示し、生成するプロジェクトにそれを再現するよう求めている場合は、仕様への忠実性を最優先の要件として扱います。
- 生成後に元の仕様と構築済みのスキーマの両方を利用できる場合は、両者を比較します。
- パスを黙って正規化したり、タグを削除したり、メディアタイプを JSON に集約したり、元のメタデータをフレームワークのデフォルト値に置き換えたりしないでください。
- dmr が元の仕様にないフレームワーク標準のドキュメントを追加する場合は、それを無効にするか、その旨をユーザーに明示してください。
- このモードでのデフォルトの目標は、すべての生成コンポーネントスキーマを文字どおり一致させることではなく、実行可能なスケルトンで公開契約をできるだけ近づけることです。
新しいプロジェクトを生成するときは環境をセットアップする
- ユーザーが新しいフォルダーにプロジェクトを作成するよう求めている場合は、ソースファイルだけでなく、環境と依存関係マニフェストも作成します。
- 新しいスタンドアロンプロジェクトでは、ユーザーがプレーンな Django スケルトンを明示的に求めていない限り、プロジェクトのベースとして
wemake-django-templateを優先します。 - 既存のリポジトリを拡張する場合や、リポジトリ内に新しいアプリだけを生成する場合は、
wemake-django-templateを後付けで導入しようとしないでください。 - 対象のリポジトリですでに別のツールが使用されていない場合は、
uvを優先します。 - 対象のリポジトリですでに Poetry を使用する
pyproject.tomlがある場合は、poetryを優先します。 - ユーザーが明示的に求めている場合、または環境が意図的に最小構成になっている場合に限り、
pipに切り替えます。 - 生成コードに必要な追加機能とともに
django-modern-restをインストールします。 - Pydantic ベースのコードを生成する場合は、少なくとも
django-modern-rest[pydantic]をインストールします。 - ローカルのドキュメントでは、JSON の解析とレンダリングを高速化するために
msgspecが推奨されているため、Pydantic プロジェクトでもdjango-modern-rest[msgspec]を含めることを優先します。 - OpenAPI のセキュリティモデルとユーザーの依頼で JWT サポートが必要な場合に限り、
django-modern-rest[jwt]を含めます。 - Python
3.11+と Django5.0+を対象にします。 - 生成したプロジェクトで OpenAPI ドキュメントの静的ファイルを提供する必要がない限り、
INSTALLED_APPSに'dmr'を追加しないでください。 - 元の仕様と構築済みの仕様を比較するためだけに、追加のスキーマ検証ライブラリをインストールしないでください。リポジトリにすでに含まれている場合、またはユーザーが明示的に求めている場合を除き、
django-modern-rest[openapi]、openapi-spec-validator、schemathesisの追加は避けてください。 wemake-django-templateを使用する場合は、プロジェクトの骨組みを手作業で作り直すのではなく、その構成に生成した DTO、コントローラー、ルーター、ドキュメントの配線、テストを追加します。
出力の構成を計画する
- 新しいアーキテクチャを考案するのではなく、既存のリポジトリ構成のうち最も近いものを踏襲します。
- 境界が明確な領域ごとに、通常は安定したタグまたは最初のパスセグメントを基準として、Django アプリを 1 つずつ作成します。
- 各アプリに
views.pyとurls.pyを作成します。 - アプリに再利用可能なリクエスト DTO とレスポンス DTO がある場合は、
serializers.pyを作成します。小規模な非公開ヘルパーモデルは、周囲のコードにより適合する場合に限り、インラインで記述します。 - 実行可能なプロジェクトのひな形ごとに、ルートの
urls.pyに OpenAPI ドキュメントの配線を追加します。 - ユーザーから追加の要望がない限り、ルート、スキーマ、ドキュメントのスモークテストに必要な最小限のテストのみを作成します。
シリアライザーを慎重に選ぶ
- デフォルトでは
PydanticSerializerを優先します。 - リポジトリですでに
MsgspecSerializerが標準として採用されている場合、またはユーザーから明示的に指定された場合に限り、MsgspecSerializerを使用します。 - ユニオン、判別子、エイリアス、NULL 許容性、詳細なフィールド制約、複合コンテンツモデルなど、複雑な OpenAPI 3.1 の機能には
PydanticSerializerを使用します。 - XML などの JSON 以外のメディアタイプがソース仕様に含まれる場合は、パーサーやレンダラーの方針とは独立してシリアライザーを選びます。シリアライザーを選ぶだけでは、ネゴシエーションは維持されません。
OpenAPI の各パーツから DTO を生成する
- リクエストボディは
Body[...]に割り当てます。 - クエリパラメーターは
Query[...]に割り当てます。 - パスパラメーターは
Path[...]に割り当てます。 - ヘッダーパラメーターは
Headers[...]に割り当てます。 - Cookie パラメーターは
Cookies[...]に割り当てます。 - クラスを重複させず、複数の操作でスキーマを共有します。
- ワイヤーフォーマットのフィールド名を維持します。スキーマ名が有効または読みやすい Python 属性名でない場合に限り、エイリアスを導入します。
- 選択したシリアライザーで適切にサポートされている場合は、仕様に記載された検証制約をエンコードします。
- レスポンスに識別子、タイムスタンプ、トークン、URL、派生値など、サーバー側で管理するフィールドが追加される場合は、入力 DTO と出力 DTO を分けます。
- リクエスト DTO とレスポンス DTO の生成に使われる再利用可能なスキーマは維持します。公開 API の契約がすでに維持されている場合は、
components.schemasとの完全一致を優先する必要はありません。
適切な dmr の構成要素を使ってビューを生成する
Controllerの数は最小限に抑えます。- 操作ごとにクラスを 1 つ作成します。用途が混在した巨大なコントローラーを構築せず、ルーターに構成させます。
operationIdが安定していて明示的な場合は、それを基にクラス名を付けます。それ以外の場合は、UserListController、UserCreateController、InvoiceRetrieveControllerのように、リソースと動詞から名前を導きます。
偽のビジネスロジックではなく、ひな形の動作を生成する
- 実行時のハンドラーは、トランスポート処理のみを担い、決定論的に動作するようにします。
- スキーマに準拠したプレースホルダーデータ、エコーバックしたリクエストデータ、または空のコレクションを返します。
204または304のようなエンドポイントには、@modify(status_code=HTTPStatus.NO_CONTENT)と-> Noneを使用します。- 低レベルのレスポンス構築が実際に必要な場合にのみ、
self.to_response(...)を使用します。 - 永続化、オーケストレーション、認証バックエンド、外部連携などを実装する箇所には、短い
TODOコメントを残します。 - ユーザーから明示的に依頼された場合を除き、ドメインワークフロー、サービス呼び出し、データアクセスロジック、価格設定ルール、権限ルール、または副作用を伴うオーケストレーションを生成しないでください。
- ユーザーから明示的に依頼された場合を除き、Django モデル、サービス、リポジトリ、または複雑な認証実装を考案しないでください。
ルーターとプロジェクトの配線を生成する
Router([...], prefix='.../')を使ってアプリのルートを構築します。- ルーター内では、ローカルコードと同じ方法で
path(...)またはre_path(...)を使います。 - 周辺のプロジェクトで明らかに省略されていない限り、生成するルートの末尾にスラッシュを付けます。
- プロジェクトのルートから
include((router.urls, 'app_name'), namespace='...')を使ってアプリのルーターを読み込みます。 - 生成する実行可能なスケルトンでドキュメントを常に利用できるよう、
build_schema(...)、OpenAPIJsonView、RedocView、SwaggerView、ScalarViewを配線します。 - ソース仕様が正式な基準である場合は、公開パスの契約を維持します。ユーザーが公開 API の形を明示的に変更するよう求めない限り、
/api/プレフィックスや末尾のスラッシュを追加したり、ケバブケースに書き換えたりしないでください。
要求された場合は、実行可能なブートストラップファイルを生成する
- 新しいプロジェクトをスキャフォールディングする場合は、選択したツールに合わせて
pyproject.tomlまたは同等のパッケージマネージャー設定ファイルも生成します。 - まだ存在しない場合は、
manage.py、Django の設定、ルートのurls.py、アプリのパッケージ初期化ファイルを生成します。 - プロジェクトで OpenAPI UI を公開する必要がある場合に限り、ドキュメントのエンドポイントを配線します。
- 最終回答に、
uv run python manage.py runserverやpoetry run python manage.py runserverのような正確なコマンドを含む、短い実行手順を追加します。
最小限の検証を生成する
- 重要なルートグループごとに、ステータスコードとレスポンスの形式を確認するスモークテストを 1 つ追加します。
- ドキュメントのエンドポイントを生成した場合は、OpenAPI のスモークテストを 1 つ追加します。
- リポジトリですでに Schemathesis を使っている場合、またはユーザーから明示的に求められた場合に限り、Schemathesis のコントラクトテストを追加します。
- ソース仕様が正式な基準である場合は、タスクの完了とする前に、生成したスキーマをソース仕様と比較します。パス、メディアタイプ、レスポンスコード、ヘッダー、セキュリティ、タグ、サーバー、トップレベルのメタデータに差異があれば報告します。
- 実行可能なスケルトンでは、
openapi、redoc、swagger、scalarの各エンドポイントが利用可能であることを確認するスモークチェックを含めます。 - この比較に外部の検証ツールを必須としないでください。直接スキーマを調べ、スモークテストを実行する方法を優先します。
完了前に、実用的な忠実性の基準を適用する
- 次の不一致は、解消が必要なものとして扱います。公開パスの契約が欠落または変更されている、ソースのメソッドが欠落している、主要なソースメディアタイプが欠落している、重要なソースレスポンスのステータスコードが欠落している、クライアントに影響するソースレスポンスヘッダーが欠落している、ソースのセキュリティスキームまたは操作レベルのセキュリティが欠落している、重要なトップレベルメタデータ(
info、externalDocs、servers、tags)が欠落している、またはドキュメントのエンドポイントが開かない。 - リクエスト DTO とレスポンス DTO、メディアタイプ、公開操作が十分に忠実で、実用的なスキャフォールドとして使える場合は、内部のコンポーネント構成の違いを解消不要として扱います。
- シリアライザーによって生成される見た目だけのメタデータの違い(例:余分なスキーマの
titleキー)は、簡潔に説明したうえで許容します。 - 解消が必要な不一致が残っている場合は、作業を続けるか、具体的な項目を挙げてユーザーの承認を求めます。
- 残る差異を解消するか、ユーザーが明示的に受け入れるまでは、完了したと主張しないでください。
翻訳ルール
- ハンドラーがシリアライザーでレンダリングできる通常の Python 値を返す場合は、戻り値の型を直接注釈してください。
- 追加のレスポンスは、
responses = (...)、@modify(extra_responses=[...])、または@validate(...)を使ってResponseSpecで記述してください。 - 空のボディを持つエンドポイントは、HTTP のルールに準拠させてください。仕様で本当に必要とされ、ユーザーが明示的な
HttpSpecのオーバーライドを受け入れる場合を除き、通常はリクエストボディを禁止するメソッドにBody[...]を付けないでください。 - リポジトリに既存の認証バックエンドがある場合は、それを再利用してください。ない場合は、バックエンドを新たに作るのではなく、宣言されたセキュリティ要件を短い
TODOで示してください。 - まずはシンプルな JSON 出力を優先してください。仕様で複数の表現が本当に必要とされる場合、またはリポジトリですでにネゴシエーションのパターンが使われている場合に限り、ネゴシエーションに特化したパーサーやレンダラーのコードを生成してください。
- ルート名は安定した snake_case にしてください。可能であれば
operationIdから導出してください。 - 新規プロジェクトでは、インストールコマンドをローカルドキュメントに合わせてください。
uv add 'django-modern-rest[msgspec, openapi]'、poetry add 'django-modern-rest[msgspec, openapi]'、 またはpip install 'django-modern-rest[msgspec, openapi]'を使い、 必要に応じて追加の extras を指定してください。 OpenAPIConfigを使って、ソースのトップレベルメタデータであるtitle、version、summary、description、terms_of_service、contact、license、external_docs、servers、tagsを保持してください。- ソース仕様が
application/jsonやapplication/xmlなど複数のレスポンスメディアタイプを使用している場合は、それらに対応するパーサーとレンダラーを生成するか、忠実性が部分的であることを明示してください。契約を黙って JSON のみに縮約しないでください。 - ソース仕様で
application/x-www-form-urlencodedが宣言されている場合は、組み込みサポートを使用してください。また、application/octet-streamやファイル形式のボディは、生成されるエンドポイントの契約で明示してください。 - ライブラリでサポートされておらず、対象プロジェクトにも実装されていないメディアタイプについては、ユーザーに次のいずれかのスキャフォールドモードを選んでもらってください。
minimal-workingモード:curl でエンドポイントを呼び出せる状態を保ちながら、TODO としてマークした最小限のパススルー用パーサーとレンダラーのプレースホルダーを生成します。strict-stubモード:NotImplementedErrorを発生させるパーサーとレンダラーのスタブを生成します。 - 最初の未対応メディアタイプについてコードを生成する前に、次の質問テンプレートを必ず使用してください。
Unsupported media type "<media_type>" is not implemented in this project. Choose scaffold mode: "minimal-working" (callable TODO placeholder) or "strict-stub" (NotImplementedError stub). - 不明なメディアタイプの完全なコーデックロジックは実装しないでください。実装はユーザーの責任です。
- デフォルトでは DMR のエラーモデルを使用してください。ユーザーがカスタムエラースキーマの維持を明示的に求めない限り、ソース固有のカスタムエラー DTO よりも
dmr.errors.ErrorModel、APIError、および関連する組み込みのエラー処理機構を優先してください。 - ドキュメントに記載されたレスポンスヘッダーは、省略せず
ResponseSpec(..., headers={...})で保持してください。 - DMR のセマンティックレスポンスは、実行可能なスケルトンを改善し、ユーザーが仕様との差異を受け入れる場合にのみ保持してください。それ以外の場合は、
DMR_SETTINGS = {Settings.semantic_responses: False}で無効にしてください。 - ドキュメントに記載されたセキュリティスキームを保持するため、実行時の認証ロジックがまだ
TODOであっても、security_schemeとsecurity_requirementでソースの OpenAPI 契約を公開するプレースホルダー認証クラスを生成してください。
出力チェックリスト
- 新規プロジェクトの依頼の場合は、環境マニフェストを作成または更新します。
- ルーティングに関わるすべてのリクエストモデルとレスポンスモデルについて、スキーマに準拠した DTO クラスを作成します。
- 型付きコントローラーとプレースホルダー実装を含む
views.pyを作成します。 - 生成したすべてのアプリに
Routerを接続するurls.pyを作成します。 - 実行可能なプロジェクトのひな形を求められた場合に限り、プロジェクトルートの URL を更新します。
- 最小限のテストを追加するか、テストを追加しなかった理由を説明します。
- ソース仕様が提供された場合は、構築したスキーマでパス、トップレベルのメタデータ、タグ、サーバー、セキュリティスキーム、レスポンスヘッダー、メディアタイプ、および空のボディのセマンティクスが保持されているかを確認します。
- 生成した実行可能なひな形で、ドキュメントのエンドポイントが利用できることを確認します。
- ソースに基づいて生成する場合は、次の項目に分けて、忠実性の概要を簡潔に示します。
保持された契約,ユーザーの承認が必要
コメント
Markdown 対応