【誰でもできる】DjangoでAPIをさくっと作っちゃう手順


# はじめに

DjangoはFlaskやFastAPIと比べて敷居が若干高い気がして初心者が理解するのに苦労しているイメージがあります。そんな方でも順番に手順を踏めば簡単にできるよ！ってことを伝えるべく記事を書いてみました。少しでも参考になればと思います。

# Handson

必要なライブラリをインストール

```
$ pip install django
$ pip install djangorestframework
```
次に、デスクトップなりどこでも良いんで作業用のフォルダ「django-api-work」作成。そうしてVScodeでそのフォルダを開きましょう。

作業フォルダに移動して以下のコマンドを実行。

```
$ cd django-api-work
$ django-admin startproject apiproject
```

※ `django-admin startproject [PJ名]`でプロジェクトが作成され、必要なファイルがコピーされてローカルに出現します。


階層構造
```
.
└── apiproject
    ├── apiproject
    │   ├── __init__.py
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    └── manage.py

2 directories, 6 files
```

次にアプリケーションを作成するので、一旦プロジェクトに移動します
```
$ cd apiproject/
```
アプリケーションの作成
```
$ python manage.py startapp apiapp
```
※ `python manage.py startapp [App名]`
```

階層構造
.
├── apiapp
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── apiproject
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-38.pyc
│   │   └── settings.cpython-38.pyc
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py
```

※ファイルが多くて混乱しますがひとつずつ必要なファイルを見ると理解できるので心配しないでください！

apiproject/settings.pyの INSTALLED_APPS以下の2行を追加
- "apiapp" : 作成したアプリ
- "rest_framework" : API作成に使用するライブラリ追加

```apiproject/settings.py
INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "apiapp", #追加
    "rest_framework", #追加
]
```

次にモデル作成

apiapp/models.py とアプリの中のmodels.pyを編集していきます。モデルを定義してここからテーブルを作成して実際のデータベースに反映していくことをやっていきます。モデルにはテーブルの定義をするイメージです。寛解はデバイス情報を管理するものを作ろうと思うので、「name」「place」「type」のようなカラムを用意しました。

```apiapp/models.py
from django.db import models

# Create your models here.
class Device(models.Model):
    name = models.CharField(max_length=256)
    place = models.CharField(max_length=256)
    type = models.CharField(max_length=256)
```

Djangoのメリットは作成したモデル(テーブル)を管理画面に認識させて、管理画面から入力してデータ追加できることです。それをするには`admin.py`に1行追加していきます。これでadminファイルがモデル(Device)を認識しました。

```python
from django.contrib import admin
from .models import Device
# Register your models here.
admin.site.register(Device) #追加
```
モデルをデータベースに反映させる作業をしていきます。この作業をしないとデータベースを覗いても何もテーブルがありません。以下の2つをやります
- [1] makemigrations : マイグレーションファイルの作成
- [2] migrate : データベースへ反映

```bash
(venv) python manage.py makemigrations
Migrations for 'apiapp':
  apiapp/migrations/0001_initial.py
    - Create model Device
```

```bash
(venv) python manage.py migrate
```

アプリを起動した際の管理者画面に入るのに必要な管理者ユーザーを作成します。UsernameとPasswordが入力できていればOKです

```bash
(venv) python manage.py createsuperuser
```

開発サーバーを起動します

```bash
(venv) python manage.py runserver
```

- `http://127.0.0.1:8000/`にアクセス

![スクリーンショット 2023-03-06 23.21.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223559/98cf6794-60f4-f2e1-4a55-b3ffdc4a7d3a.png)

- `http://127.0.0.1:8000/admin`にアクセス


![スクリーンショット 2023-03-06 23.21.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223559/624e29e9-a946-8a17-dc17-1a7e5ad33153.png)


- 管理画面

![スクリーンショット 2023-03-06 23.21.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223559/697fcfbc-ddcd-73bc-ae72-c5e7fed6a412.png)

- 実際にデータベースに簡単にデータ追加できます
- 入力したら「SAVE」

![スクリーンショット 2023-03-06 23.22.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223559/97fa2ab6-744c-cc13-c964-f2ceb08d298a.png)

ここからがAPIの本番です。DjangoでAPIを実装するには、Django REST framework (DRF)というライブラリを使用していきます。これからやることは以下の3つです。



- [1] Serializer
    -  データの入出力を扱い、モデルへの橋渡しをするクラス
    -  APIの Request/Responseに特化したクラス
    -  シリアライザの種類
        -  serializers.Serializer
        -  serializers.ModelSerializer (これが一番利用されている？)
            -  JSON, XML など ↔︎ Django の model の変換をするクラス。
            -  デフォルトで model のフィールドを読み込んでくれる
            -  デフォルトで create() メソッドと update() メソッドが実装されている
            -  Readonly なフィールド設定可能
        -  serializers.ListSerializer
            -  複数のモデルを扱う前提
            -  通常 ListSerializer を直接使うことはない
            -  ListSerializer の挙動をカスタマイズしたい場合にのみ使用
- [2] View
    - DRFにおけるViewとは、ユーザーからのアクセス（リクエスト）に対して、どのAPIを使用するかを決定、処理を行って返却する役割
    - Viewの作成
        - Generic View (generics.XXXXX)
            - DRFがデフォルトで提供している汎用的なViewの総称
            - よく使う機能毎にViewを提供してくれているので、自分が実装したい機能に合わせて適切なViewを継承
                - CreateAPIView : POST : 登録
                - ListAPIView : GET : 一覧取得
                - RetrieveAPIView : GET : 単体取得
                - UpdateAPIView : PUT/PATCH : 更新
                - DestroyAPIView : DELETE : 削除
        - ViewSet (viewsets.ModelViewSet)
            - DRFからデフォルトで提供されているDBとのやりとりに特化したViewで、取得, 一覧, 登録, 更新, 削除を一括で実装
            - ViewSetを利用するメリットは複数機能を一括で実装してくれるのでコード記述量が減る
            - 大体ViewSetsを使う例がでてくるので、サンプルにもこまらないのかなと


※ GenericViewもViewSetsも便利ですけど、DBを使わない場合には使えません。そういう場合は「APIView」か「api_view」を使います。 APIViewが「クラスベースのView」 api_viewが「関数型のView」
 

- [3] Router
    - urls.pyにルーティングルールを追加
    - DefaultRouter は Router のルート画面にアクセスしたときに API のリンク一覧を見せてくれる
    - Routerで登録できるのは、ViewSetだけ
    - DefaultRouterとSimpleRouterがあって、あまり機能的には変わらない
    - ジェネリックビューを使用している場合はDjangoと同様に、as_view()を使用してルーティングする

※参考記事

https://note.crohaco.net/2018/django-rest-framework-serializer/

https://note.crohaco.net/2018/django-rest-framework-view/

https://akiyoko.hatenablog.jp/entry/2022/12/01/064746#%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E5%85%A8%E4%BD%93%E5%83%8F%E3%82%92%E6%8A%8A%E6%8F%A1%E3%81%97%E3%82%88%E3%81%86


apiapp/serializers.py (new)

```serializer.py
from rest_framework import serializers
from .models import Device 

class DeviceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Device 
        fields = '__all__'
```

apiapp/views.pyを編集していきます。
- POINT
    - serializerを読み込む
    - `queryset`と`serializer_class`の設定

```apiapp/views.py
from django.shortcuts import render
from rest_framework import viewsets
from .models import Device
from .serializers import DeviceSerializer


class DeviceAPIView(viewsets.ModelViewSet):
    queryset = Device.objects.all()
    serializer_class = DeviceSerializer

```


apiapp/urls.pyを編集してルーティングの設定をしていきます。

```apiapp/urls.py
from django.urls import path
from rest_framework import routers
from .views import DeviceAPIView 

router = routers.DefaultRouter()
router.register(r'device', DeviceAPIView)

```


project側のurls.pyを編集していきます。

```apiproject/urls.py
from django.contrib import admin
from django.urls import path, include
from apiapp.urls import router as device_router

urlpatterns = [
    path("admin/", admin.site.urls),
    path("device/", include(device_router.urls)),
]
```
※ `path(相対URL, 紐付ける関数（クラス）, ページ名)`or `path(相対URL, include(紐付けたいurls.py))`
※ `include`メソッドは、ビュー関数ではなく、別のurls.pyと紐付けたいときに使えるメソッド
- urls.pyは、URLとViewの紐付けが主な役割
- urls.pyの書き方は、pathメソッドに正しい値を渡すこと
- path以外にも、includeやre_pathを覚えておくと便利


これでひと通り作業は終わりです。以下コマンドで起動

```
$ python manage.py runserver
```

`http://127.0.0.1:8000/device/`にアクセスして以下の画面が表示されればOK

![スクリーンショット 2023-03-07 10.06.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223559/02899e5e-1665-b562-5c62-c3a22ecbf36d.png)


# 終わりに

APIをサクッと作るという観点でいうと、やはりflaskやfastapiの方が楽です。お試しでやる場合はそちらをオススメはします。ですが慣れればそこまで難しくもないので使っているうちに慣れてくると思いますので初学者の方はくじけづ頑張りましょう🔥