スポンサーリンク

Python/Djangoで爆速でRESTAPI作成する方法(Swaggerも使用)

Python
スポンサーリンク

本記事の対象者

  • DjangoでサクッとAPIを作成したい方
    ※今回はシンプルなCRUDのRESTAPIを作成していきますので複雑なカスタマイズ方法などは記載しません。

ローカルで用意する環境

  • Django3.1

下記がDjango環境構築をまとめた記事になりますのでまだの方はこちらからご確認ください。

必要ライブラリのインストール

pipコマンドを実行してインストールします。

djangorestframeworkdjango-filterdrf-yasgのインストールを実行します。

$ pip install djangorestframework
$ pip install django-filter
$ pip install drf-yasg

dockerで環境構築している方はコンテナ内で実行してください。私のブログの記事通りdockerで環境構築した方はrequirements.txtに上記ライブラリを記述してコンテナをビルドしなおす方法でもOKです。docker環境の場合、コンテナをビルドしなおすとrequirements.txtに記載しておかないと一度インストールしたライブラリも再インストールしなおす必要があるため最初からrequirements.txtに記述したほうが良いと思います。

Djangoに新規アプリケーションを作成

manageコマンドをコンソールで実行します。

$ python manage.py startapp my_api

成功するとDjangoディレクトリ直下にmy_apiというディレクトリが作成されてます。

モデルの作成

RESTAPI用のモデルを作成していきます。今回は下記のようなモデルを作成したいと思います。
ちなみにこのAPIを使って簡単なTodoアプリを作る想定です。

まずは先ほど作成したmy_api直下にmodelsディレクトリを作成します。
modelsディレクトリ直下に下記3ファイルを作成します。

  • __init__.py
  • base_model.py
  • task.py

メインのmodelの中身はtask.pyに記載します。base_modelはどのmodelでも共通で追加する作成日時などを記述しています。

# __init__.py
from .base_model import BaseModel
from .task import Task
# base_model.py
from django.db import models


class BaseModel(models.Model):
    """
    全model共通のフィールドを記述
    """
    class Meta:
        abstract = True

    created_at = models.DateTimeField(
        verbose_name='登録日時', 
        auto_now_add=True
    )

    updated_at = models.DateTimeField(
        verbose_name='更新日時',
        auto_now=True
    )
# task.py
from django.db import models
from my_api.models import BaseModel
from datetime import date


class Task(BaseModel):
    class Meta:
        db_table = 'task'
        verbose_name = verbose_name_plural = 'タスク' 

    PRIORITY_CHOICES = (
        (0, '小'), 
        (1, '中'),
        (2, '大'),
    )

    todo = models.CharField(
        verbose_name="やること",
        max_length=255
    )

    priority = models.IntegerField(
        verbose_name="優先度",
        choices=PRIORITY_CHOICES
    )

    complete_flag = models.BooleanField(
        verbose_name="完了フラグ",
        default=False
    )

    def __str__(self):
        return self.todo

※ちなみにmy_apiディレクトリ直下にmodels.pyというファイルが作成されており、そこに複数モデルを羅列するように記述していくことがDjangoのモデル作成ではデフォルトのようです。
ですが今回は1モデルごとにファイルを切り分けられるように作成しています。今回の作成方法は正直好みですのでmodels.pyに直接記述する方法でも問題ありません。
個人的にmodelはファイル分けたほうが見やすいなと思ったのでこのような構成にしています。

settingsの修正

settings.pyを下記のように修正します。「# 追加」と書かれている箇所を追加してください。デフォルトで記述されているものを削除しないように注意してください。

# settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'my_api', # 追加
    'rest_framework', # 追加
    'django_filters', # 追加
    'drf_yasg', # 追加
    'app', # 追加
]

# 下記をすべて追加
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
}

マイグレーションの実行

先ほど作成したmodelをもとにマイグレーションファイルを作成します。下記コマンドを実行してください。

$ python manage.py makemigrations

上記コマンドを実行することでmodelファイルに合わせてマイグレーションファイルが作成されます。次にマイグレーション実行します。下記コマンドを実行してください。

$ python manage.py migrate

これでDBにtaskテーブルが生成されました。

serializerの作成

my_api直下にserializersディレクトリを作成します。
その後、serializersディレクトリ直下に下記2ファイルを作成します。

  • __init__.py
  • task_serializer.py
# __init__.py
from .task_serializer import TaskSerializer
# task_serializer.py
from rest_framework import serializers
from my_api.models import Task


class TaskSerializer(serializers.ModelSerializer):
    class Meta:
        model = Task
        exclude = [
            "created_at",
            "updated_at",
        ]

viewsetの作成

my_api直下にviewsetsディレクトリを作成します。その後viewsets直下に下記2ファイルを作成してください。少しだけ説明するとtask_viewset.pyのfilter_fieldsにcomplete_flagを設定しておくとGETパラメータの検索項目と使用できるようになるためです。

  • __init__.py
  • task_viewset.py
# __init__.py
from .task_viewset import TaskViewSet
# task_viewset.py
from rest_framework.viewsets import ModelViewSet
from my_api.models import Task
from my_api.serializers import TaskSerializer


class TaskViewSet(ModelViewSet):
    queryset = Task.objects.all()
    serializer_class = TaskSerializer
    filter_fields = {
        'complete_flag': ['exact'],
    }

ルーティングの修正

下記の2ファイルを修正します。app配下のurls.pyにベースのルーティングを設定しmy_apiにもurls.pyを作成し、下記のように記述を追加します。

  • app/urls.py
  • my_api/urls.py
# app/urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include
from my_api.urls import router
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi

schema_view = get_schema_view(
   openapi.Info(
      title="Snippets API",
      default_version='v1',
      description="Test description",
      terms_of_service="https://www.google.com/policies/terms/",
      contact=openapi.Contact(email="contact@snippets.local"),
      license=openapi.License(name="BSD License"),
   ),
   public=True,
   permission_classes=[permissions.AllowAny],
)

urlpatterns = [
    path('admin', admin.site.urls),
    url(r'^api/', include(router.urls)),
    url(r'^swagger/$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
]
# my_api/urls.py
from . import views
from rest_framework import routers
from my_api.viewsets import TaskViewSet

app_name = 'my_api'
router = routers.DefaultRouter()
router.register(r'tasks', TaskViewSet)

これで/api/tasksというURLでRESTAPIが使用できるようになりました。

動作確認

それではブラウ上で確認してみましょう。runserverコマンドを実行します。

$ python manage.py runserver

コマンドが成功したら下記URLにアクセスしてください。そうすると下記画面が表示されます。

http://127.0.0.1:8000/api/tasks/

このURLはGETパラメータになるためデータが存在する場合Listでデータを取得できます。
今はデータがないので作成してみます。下に入力欄があるのでそこを入力してPOSTしましょう。

その後、再度 http://127.0.0.1:8000/api/tasks/ にアクセスしてください。そうするとデータが取得できます。

SwaggerでAPI一覧を確認

今回はAPIのメソッドを限定せずに作成していますので、GET、POST、PUT、PATCH、DELETE全てが使用可能です。API一覧を確認するためにSwaggerもインストールと設定もこれまでに終わらせているので下記URLにアクセスすると画面が表示されます。

当然Swaggerからメソッドの実行も可能です。またドキュメントをSwaggerから作成することも可能ですのでその点でも非常に便利なライブラリです。DjangoでAPIを作成する際はぜひ試してみてください。

コメント