Django REST frameworkでAPIドキュメントを自動生成 & ドキュメント画面からPOSTする方法

本記事ではDjango REST frameworkでAPIを作成した際に、そのAPIドキュメント（使用方法などの解説）を自動生成する方法について解説します。

### 手順0：DRF（Django REST framework）

今回は、**version：3.10.3**を使用しています。
なお、現在（2020年9月）の最新バージョンは**version:3.11.1**です。


### 手順1：追加のパッケージをインストール

APIドキュメントの自動作成に必要なパッケージをインストールします。

```
pip install coreapi
pip install Pygments
pip install Markdown
```

### 手順2：urls.pyにdocページを定義

Django Appのベースとなっているappのフォルダのurls.pyに対して、

`from rest_framework.documentation import include_docs_urls`

を追記して、`include_docs_urls()`を使用できるようにします。

その上で、アプリケーションのurls.pyに対して、以下のように、`path("docs/"・・・`、を設定をします。

```python
...

from rest_framework.documentation import include_docs_urls

urlpatterns = [
    path("admin/", admin.site.urls),
    path("docs/", include_docs_urls(title='API Document')),
    ...

```

これで、/docs（例えば、http://localhost:8000/docs/ ）にアクセスすれば、以下の図のようなAPIのドキュメントページが表示されます。

![api1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191401/5b76d5ed-f429-5078-c8f3-35af5428720f.jpeg)


**※エラー対策**
docsページにアクセスした際に、`autoschema' object has no attribute 'get_link' django`
というエラーが表示された場合は、

アプリケーションのフォルダのsetttings.pyに、以下のように
`'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema'`
を追記します。

```python
...
REST_FRAMEWORK = {
    ...
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema'
}
```

これはDRFのバージョン3.10以上を使用している場合に発生します。

（参考）Django REST framework 3.10
https://www.django-rest-framework.org/community/3.10-announcement/


### 手順3：doc画面の見方

画面左下には、AuthenticationとSource Codeというメニューがあります。

[3.1] Authenticationを展開すると、ログインすることができます。
ここでログインしておけば、ログインした状態でこのdoc画面からAPIを叩くことができます
（APIの叩き方は後ろの節で解説します）。

[3.2] Source Codeでは画面の右側に、coreapiを使用した

- shell
- Javascript
- Python

の、各APIに対する実装コードを表示させることができます

![api2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191401/e988967d-d82f-3991-e30f-7c6f8fd46a6b.jpeg)


**※エラー対策**
なぜかdoc画面ではなく、普通のAPI画面に行く場合は、Django Admin画面から一度ログインした状態で、docs/ にアクセスすると、docs画面が表示されます（原因不明）。


### 手順3：APIの説明を整える

現時点では各APIに対して、その動作の説明が入っていない状態です。
（readに関してのみURLで{id}をとるので、必須パラメータとして「id」が自動的に記述されています）

![api3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191401/078cb64a-02f8-7531-fb96-c9b4c1c0c312.jpeg)



ここに各APIの説明を追加します。

該当するappのviews.pyにある、viewsets.ViewSetなどを継承している「ViewSetクラス」に対して、コメントを記載すれば、APIの説明としてdocsに反映されます。

例えば、viewsets.ViewSetであれば、
list、create、retrieve、update、partial_update、destroyの各クラスにAPIが分かれているので、
それらの各クラスに合わせてAPIの説明を記述します。

以下のような実装になります。

```python

class DatasetViewset(viewsets.ViewSet):
    """
    list:
    全データセットの情報を取得する。

    create:
    新規にデータセットのメタ情報を作成する。

    retrieve:
    pkで指定した個別データセットの情報を取得する。
　　　
    """

    def list(self, request):
        ・・・
```

すると、APIのdocsには、以下のように記述した説明が追加されます。

![api4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191401/c724c8ad-5933-833e-e03c-44519365cd12.jpeg)

なお、APIの説明を記載する際に、どのような内容を記述すべきかについては本記事の最後に説明します。


### 手順4：APIを叩けるようにする

このdoc画面からAPIを叩くことが可能です。
上図画面中央の緑色の「Interact」ボタンをクリックすると、APIを叩く画面が出てきます。

GET系の場合はこれで良いのですが、create (POST) やPUT系が現在不完全な状態です。

また、さきほどの図においても、createやputに必要なパラメータが記載されておらず、APIの説明として不十分です。

createの「Interact」ボタンをクリックしても、以下の図のような画面が表示されPOSTするパラメータ値を書き込めません。

![api5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191401/7bc24af9-1abc-74bf-b4c7-f36a120d936b.jpeg)

このPOST系やPUT系のAPIの説明を整え、POSTのAPIを叩けるようにする方法はいろいろあります。

Django REST frameworkのSchemaがその解説になります。
https://www.django-rest-framework.org/api-guide/schemas/


ひとつの簡単な方法は、以下のように
`def get_serializer(self):`
のコードをViewSetクラスに記載し、さらにメソッドごとに、
そのメソッドで使用しているシリアライザーを記載して、流用する作戦です。

```Python
class DatasetViewset(viewsets.ViewSet):
    """
    list:
    全データセットの情報を取得する。

    create:
    新規にデータセットのメタ情報を作成する。

    retrieve:
    pkで指定した個別データセットの情報を取得する。
    """

    def get_serializer(self):
        """APIドキュメント用"""
        if self.action is "create":
            return DatasetCreateInputSerializer()
        elif self.action is "update":
            return DatasetUpdateMetadataInputSerializer()

    def list(self, request):
        ・・・
```

すると、doc画面は次のように変わります。

![api6.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191401/0bf4948c-e2cc-6690-74d8-b2950c64bf98.jpeg)


上の図は少し見づらいですが、createとupdateにそれぞれのAPIで必要なパラメータが記載されました。

最後に気になるのは、各パラメータの説明（description）に記載がない点です。

きちんとそのAPIで使用する引数を解説するために、descriptionを記載するには、models.pyで

```python
name = models.CharField(blank=False, max_length=100, unique=True, help_text="プロジェクト名")
```

のように、引数「help_text」に説明を記載します。

もし、serializersで、モデルに依存しないserializers.Serializerでのクラスを作成していた場合も、そのフィールドの引数「help_text」に説明を記載します。



すると、doc画面が以下のようになり、「データセット名」などと、Descriptionに各Parameterの説明が入ります。

![api7.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191401/fc9ac671-e1e2-5bbd-e006-7ba18870cb25.jpeg)

そしてこの状態（def get_serializer()をViewSetクラスに記載して、メソッドごとに、そのメソッドで使用しているシリアライザーを指定）した状態であれば、

画面中央の緑色の「Interact」ボタンをクリックすると、引数が表示された状態で、APIを叩く画面が出てきます。


![api8.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191401/3bb174c9-656f-54da-f8fe-153fa63dc6f8.jpeg)


これでAPIを叩く際の各パラメータの値を左側に入力して、右下の「Send Request」をクリックすれば、このAPIをPOSTすることができます。


### 手順5：APIの説明に記載して欲しいこと

最後にAPIの説明に記載して欲しいことを解説します。

**大切なのは、APIを使うユーザーの視点に立ち、分かりやすく、理解しやすく、APIのドキュメントを作成しようという思いやりの気持ちです。**


記載して欲しい内容は、APIをシステム内部だけで開発チームのみが使用する場合と、APIを外部公開する場合で大きく変わります。

どちらにせよ、

- APIの動作サマリー（生み出す成果）
- APIの動作の詳細（UML図へのリンクなどもあれば、リンクを記載）
- APIの正常形でのHTTPレスポンスステータスコードと返ってくる内容
- 引数（名前、その説明、必須かどうか、型）
- 異常形でのHTTPレスポンスステータスコードと返ってくる内容

は欲しいところです。

その他、APIに記載すべき内容については

●書籍「Web APIの設計」
https://www.amazon.co.jp/dp/4798167010/

●GoogleのAPI設計ガイド
https://cloud.google.com/apis/design

●MSのAPI設計ガイド
https://docs.microsoft.com/ja-jp/azure/architecture/best-practices/api-design

●APIスタイルブック
http://apistylebook.com/

などを参考に、自分たちのチームでどの程度まで書くのかすり合わせておくのが良いかと思います。


以上、 Django REST frameworkでAPIドキュメントを自動生成 & ドキュメント画面からPOSTする方法でした。


---

### 備考

**【情報発信】**
読んだ書籍の感想などに加え、IT・AIやビジネス・経営系で、私が面白いと思った記事やサイトをTwitterで発信しています。
これらの分野の情報を収集したい方はぜひフォローしてみてください♪
（海外の情報が多めです）

小川雄太郎@ISID_AI_team
https://twitter.com/ISID_AI_team



**【その他】**
私がリードする、「AIテクノロジー部開発チーム」ではメンバを募集中です。興味がある方は
[こちらのページ](https://www.isidgroup.com/u/job.phtml?job_code=430)
から、お願い致します♪

**【そくめん君】**
いきなり応募は・・・という方は、カジュアル面談を「そくめん君」で行わせていただいております。
こちらもぜひご利用ください♪
https://sokumenkun.com/2020/08/17/yutaro-ogawa/


【免責】本記事の内容そのものは著者の意見/発信であり、著者が属する企業等の公式見解ではございません

---

#### 本記事のその他、参考文献

- [Built-in API documentation](https://www.django-rest-framework.org/coreapi/from-documenting-your-api/)
- [データコンペサイトを作る DjangoRestFramework編](https://nykergoto.hatenablog.jp/entry/2019/12/22/%E3%83%87%E3%83%BC%E3%82%BF%E3%82%B3%E3%83%B3%E3%83%9A%E3%82%B5%E3%82%A4%E3%83%88%E3%82%92%E4%BD%9C%E3%82%8B_drf%E7%B7%A8)
- [AttributeError: 'AutoSchema' object has no attribute 'get_link' と出てきてDRFのAPIドキュメント生成が使えない場合の対処](https://qiita.com/checche/items/b705a8a2c6e7858d203a)