コンテンツにスキップ

APIドキュメント(上)#

2024 iThome鉄人レース

これはDjango Ninjaシリーズチュートリアルの第17回です。ここから第4章——APIドキュメントを開始します。

コードに基づくAPIドキュメントの自動生成」は、Django Ninjaの大きなセールスポイントです。

実際、「APIドキュメントの自動化」は、私が職場のプロジェクトをDjango REST frameworkからDjango Ninjaへ移行させる際の最優先の検討事項であり、私がDjango Ninjaを学び始めるきっかけでもありました。

Django NinjaはAPIドキュメントを手作業で作成する(私たちはAPI Blueprintを使用していました)時間を大幅に省いてくれます。特にAPIの仕様が変更された際、ドキュメントを同期して修正する必要がないため、ドキュメントの保守にかかる労力を大きく減らすことができます。

この機能がいかに重要であるかが分かるでしょう。

チュートリアルの順序に関する考慮#

では、なぜシリーズの第17回の記事——つまりこの記事になって、ようやくDjango NinjaのAPIドキュメント機能を紹介し始めるのでしょうか?

その理由は、優れたAPIドキュメントを生成するには、スキーマの使用についてある程度理解している必要があるからです。そのため、第3章の後に配置せざるを得ませんでした。

それでは、Django Ninjaを使用して高品質のAPIドキュメントを生成する方法について探求を始めましょう。

この記事のすべてのコードの変更は、こちらのPRを参考にしてください。

GitHubサンプルプロジェクト#

👉 Django-Ninja-Tutorial


Documentation as Code#

現代のソフトウェア開発において、「Documentation as Code」(DoC)は徐々に認知されつつある理念です。

DoCとは、ドキュメントとコードを密接に結合させ、開発者が「ソフトウェアコードの開発と同じプロセスとツールを使用」してドキュメントを作成および保守することを指します。

ドキュメントはコードの変更に伴って自動的に更新され、両者は常に一貫性を保ちます

これは開発効率を向上させるだけでなく、ドキュメントが古くなることによるコミュニケーションの滞りや誤解を減らします。

Django Ninjaの自動ドキュメント生成機能は、間違いなく「Documentation as Code」の精神を実践するものです。

APIのルーティング、view関数、スキーマなどのコードを記述することで、OpenAPI標準に準拠したドキュメントを自動生成し、コードが変更された際にも、これらのドキュメントは手動で保守することなく自動的に変更結果を反映します

Django NinjaでAPIドキュメントを自動化する2つのポイント#

Django Ninjaにおいて高品質のAPIドキュメントを生成するには、主に2つの重点が関わってきます:

  1. Django Ninjaの設定:Django Ninjaには、APIドキュメントの詳細を制御するための設定がいくつか組み込まれています。これがこの記事の重点です。
  2. Pydanticの設定:これは次の記事で探求する内容で、スキーマを効果的に定義し、さまざまな詳細をAPIドキュメントに自動的に反映させる方法を説明します。

ここまで読んで、少し期待が高まってきたのではないでしょうか?☺️


プロジェクトのAPIドキュメントの現状#

ドキュメントの品質を抜本的に強化し始める前に、現在のAPIドキュメントがどれほど「簡素」であるかを見てみましょう。

Djangoサーバーを起動した後、以下のURLにアクセスすると、現在のAPIドキュメントを確認できます:

http://127.0.0.1:8000/docs

現在のドキュメントの内容は以下の通りです:

開発者にとって有用であり、読みやすいか」という観点から、簡単な分析を行います。

問題点#

まず第一に、グループ化されていません

Djangoのuser appとpost appのAPIが混ざってしまっており、APIが増えるにつれて非常に雑然としてきます。これは最優先で解決すべき問題です。

次に、「Get Users」や「Create Post」などのAPIの説明は、明らかにview関数名から自動変換されたものです。情報が限られており、十分に口語的でなく、詳細でもありません。簡単に言えば、「読者に優しくない」のです。

唯一のPOST APIをクリックして内容を見てみましょう:

内部ページの説明にある「記事の追加」は、実はview関数のdocstringから取得されたものです:

@router.post(path='/posts/')
def create_post(...) -> tuple[int, dict]:
    """
    記事の追加
    """
    ...

さらに、HTTPリクエストボディの例を見てみましょう:

{
    "title": "string",
    "content": "string",
    "user_id": 0
}

これは理想的とは言えません"string"のような例は、「型」を表しているだけで、現実世界の記事のタイトルやコンテンツをシミュレートしていません。


上述の問題こそが、私たちがAPIドキュメントを改善すべき重点です。

このうち、リクエストボディの例はスキーマ設定に関係するため、次回の記事で重点的に扱います。

この記事では、まずDjango Ninjaの設定に焦点を当て、一つずつ紹介していきましょう。

1. Tagsを使用したAPIのグループ化#

私たちが最初に解決すべきは、APIのグループ化(分類)問題です。

ドキュメント構造をより明確にするため、Django NinjaはTagsを使用してAPIをグループ化することをサポートしています。ドキュメントの構成に役立つだけでなく、開発者やユーザーが必要なAPIをより早く見つけられるようになります。

Tagsによるグループ化は、2つの場所で設定できます。

一次ルーティングでのグループ化#

最も一般的な方法は、一次ルーティングで設定することです:

# NinjaForum/api.py
api.add_router(prefix='', router='user.api.router', tags=['User'])
api.add_router(prefix='', router='post.api.router', tags=['Post'])

なぜなら、同じDjango appのAPIは、通常同じグループになるからです。

ルーティングデコレータでのグループ化#

ルーティングデコレータでグループ化を設定することもできますが、これは比較的「例外的」な状況であり、主に以下の場合に使用されると私は考えています:

  1. プロジェクト全体でDjango appが1つしかない。
  2. 同じDjango appで異なるグループ化が必要である。

例えば以下の例では、Django appは区別されていませんが、グループ化の要件が存在します:

from ninja import NinjaAPI

api = NinjaAPI()

@api.get("/users/", tags=["User"])
def get_users(request):
    ...

@api.post("/posts/", tags=["Post"])
def create_post(request, title: str):
    ...

ほとんどの場合、一次ルーティングでグループ化を行うことをお勧めします。

そうしないと、上の例のように一つ一つタグ付けすることになり、実践するには少し煩雑です。


2. ルーティングデコレータのドキュメント設定#

Django Ninjaのルーティングデコレータは、基本的なAPIパスを設定できるだけでなく、APIの説明テキストを追加することも可能で、これらの内容は生成されたAPIドキュメントに直接反映されます。

これらの設定を通じて、APIのパラメータ、レスポンス、さらには意図に関する説明を追加し、ドキュメントをより包括的なものにすることができます。

descriptionおよびsummaryパラメータを通じて、各APIルーティングに説明を提供できます。ただし、descriptionは上述の「docstringからAPI説明への変換」の効果を置き換えてしまうため、私は通常summaryだけを記述します。

何しろ私たちはPythonを書いているのですから、docstringは必須です!

コードは以下の通りです:

@router.get(..., summary='記事リストの取得')
def get_posts(...) -> QuerySet[Post]:
    """
    記事リストの取得
    """
    ...

ここまでの実際の改善効果:(グループ化、API説明)

非常に良いですね!


3. NinjaAPIの設定#

NinjaAPIクラスの初期化設定を通じて、いくつかのグローバルなAPIドキュメントの詳細をカスタマイズすることができます。例えば:

# NinjaForum/api.py
from ninja import NinjaAPI

api = NinjaAPI(
    title="忍者フォーラムAPI",
    version="1.0",
    description="これは忍者フォーラムのAPIドキュメントであり、読者の参考用です"
)

対応する実際の効果:

NinjaAPIには多彩な初期化オプションが用意されており、要件に合うものが見つかるかもしれません。

ここは簡単な例示に過ぎませんので、その他の設定の詳細については、ドキュメントを参照してください。


まとめ#

この記事では、Django NinjaがAPIドキュメントを自動生成する際の一般的な設定を探求し、「Documentation as Code」の精神を実現させました——コードとドキュメントの整合性を容易に保ち、手動保守の手間を減らします。

しかし、APIドキュメントの品質は、私たちがスキーマ内の詳細をどのように定義するかにかかっています。

次に、このトピックについて深く掘り下げ、PydanticのFieldパラメータ設定を通じて高品質なドキュメントの例を提供し、APIドキュメントの可読性と明確さをさらに向上させる方法を説明します。