自分だけのクイズ作成 - Quipha公開中

【Django4】Django REST FrameworkでAPI作成

Django
スポンサーリンク

はじめに

今回はDjango REST Frameworkを利用して、RESTfulなAPIを作成してみます。

Djangoの環境とプロジェクトの作成方法は以下をご覧ください。

また、今回はデータベースにMySQLを使用しますので、以下を参考に環境を構築してください。

MySQLに依存したSQLを使用するわけではありませんので、他のDBでも問題ございません。

使用するバージョン
  • Windows 11 / 10
  • macOS Monterey (M1)
  • Python 3.10.2
  • Django 4.0.2
  • Django REST Framework 3.13.1

WindowsでもMacでも同様に作成できます。

他にも私のブログで、Djangoについて解説している記事がありますのでご覧ください。

Django REST Frameworkとは

まずAPIとは、Application Programming Interfaceの略です。
今回作成するのはWeb APIであり、HTTPやHTTPS通信でデータのやり取りを行うことができます。

Django REST Frameworkを使用することにより、Djangoフレームワークで簡単にAPIの実装を行うことができます。
バックエンドのAPIサーバーの実装を行う場合に便利です。

RESTful APIにつきましては、詳しい解説はここでは行いませんが、詳しくは調べてみてください。

Django REST Frameworkのインストール

Djangoアプリケーションが動作しているPython環境に、Django REST Frameworkをインストールします。
今回はVS Codeを使い、Dockerコンテナで作業していますので、以下のファイルを修正します。

一番最後の行を追加します。

.devcontainer/Dockerfile
FROM python:3
ENV PYTHONUNBUFFERED 1
RUN pip install django
RUN pip install mysqlclient

RUN pip install djangorestframework

F1キーをクリックし、コンテナをリビルドします。(Remote-Containers: Rebuild Container)

コンテナ構築後、以下のコマンドでDjango REST Frameworkのバージョンを確認します。

$ pip show djangorestframework

Name: djangorestframework
Version: 3.13.1
Summary: Web APIs for Django, made easy.
Home-page: https://www.django-rest-framework.org/
Author: Tom Christie
Author-email: tom@tomchristie.com
License: BSD
Location: /usr/local/lib/python3.10/site-packages
Requires: django, pytz
Required-by:

VS Codeインストール

VS Codeのインストール方法は、以下の記事にまとめましたのでご覧ください。

VS Codeのオススメ設定や拡張機能などは、以下の記事にまとめました。

Djangoプロジェクトの作成

以下のコマンドで、Djangoプロジェクトを作成します。
最後にドットを付けて、同じ階層にプロジェクトファイルを作成します。

$ django-admin startproject djangoApiApp .

「djangoApiApp」はプロジェクト名ですので、任意で指定してください。

Djangoのデータベースの設定を変更します。
デフォルトでsqlite3が指定されていますが、MySQLに変更します。

djangoApiApp/settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django_sample',
        'USER': 'root',
        'PASSWORD': 'password',
        'HOST': 'db',
        'PORT': '3306',
    }
}

DB名やユーザ、パスワードなどは、docker-compose.ymlの「db」に記載の通りです。

以下の項目も修正します。(言語とタイムゾーンの修正)

djangoApiApp/settings.py
LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

設定ファイルについては、SECRET_KEYやデータベースの接続情報などの機密情報が含まれます
GitHubの公開リポジトリなどに、そのままプッシュしてしまうのは危険です。

今回は割愛しますが、以下の記事も参考にしてください。

他にも、APIキーなど他人に知られてはいけない情報は、ソースコードに含めないように気を付けましょう。

アプリ追加と設定

追加

以下のコマンドで、Djangoプロジェクトにアプリを追加します。
商品マスターを想定したアプリで、APIの実装を行います。

$ python manage.py startapp products

設定の修正

サイトのsettings.pyに、アプリを追加します。

djangoApiApp/settings.py
INSTALLED_APPS = [
...
    'rest_framework',
    'products',
]

Django REST Frameworkを使えるように、「rest_framework」を指定します。

スポンサーリンク

モデルとテーブルの作成

モデルの作成

テーブル定義に合わせたモデルを作成します。
商品を想定したモデルを作成しました。

products/models.py
class Product(models.Model):

    name = models.CharField(max_length=200)
    price = models.IntegerField()

以下のコマンドでマイグレーションファイルを作成します。

$ python manage.py makemigrations products

以下のファイルが自動で作成されます。

products/migrations/0001_initial.py
# Generated by Django 4.0.3 on 2022-04-06 13:44

from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Product',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=200)),
                ('price', models.IntegerField()),
            ],
        ),
    ]

以下のコマンドでマイグレーションを実行し、テーブルを作成します。

$ python manage.py migrate

phpMyAdminから確認しましょう。

http://localhost:8080/

「products_product」というテーブルが作成されました。

管理画面での確認

Djangoの管理画面からも確認してみましょう。
まずは、管理画面にログインするためのユーザーを作成します。

以下のコマンドを実行します。

$ python manage.py createsuperuser

ユーザ名、メールアドレス、パスワードが聞かれますが、任意で指定してください。

以下のコマンドで開発サーバーを起動します。

$ python manage.py runserver

以下のURLにアクセスします。

http://localhost:8000/admin/

管理画面が表示されますので、先ほど作成したユーザでログインを行います。

管理画面にアクセスすることができました。

今回テーブルを作成した、商品マスタを編集できるようにします。
以下のファイルを修正します。

products/admin.py
from django.contrib import admin

# Register your models here.

from .models import Product

admin.site.register(Product)

画面を更新すると、商品テーブルのマスタメンテが追加になりました。

新規登録などを行うことができます。

一覧を表示すると、「xx object (1)」のように表示されます。

名前が表示されるように、モデルを修正します。

products/models.py
from django.db import models

# Create your models here.


class Product(models.Model):

    name = models.CharField(max_length=200)
    price = models.IntegerField()

    def __str__(self):
        return self.name

画面を更新すると、一覧に名前が表示されるようになりました。

これ以降でAPIを試す際に、phpMyAdminや管理画面を利用して確認すると良いでしょう。

Serializerクラスの作成

APIでデータのやり取りを行うためのシリアライザーを作成します。
以下のファイルを作成します。

products/serializers.py
from rest_framework import serializers
from .models import Product


class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ['name', 'price']

ビューの作成

APIの処理を、ViewSetを使用して実装します。
それにより例えば、一覧や詳細データの取得、新規登録、更新、削除などの処理が使えるようになります。

ここではModelViewSetを使用して、以下のように実装します。

products/views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer


class ProductViewSet(viewsets.ModelViewSet):

    queryset = Product.objects.all()
    serializer_class = ProductSerializer

ModelViewSetは、以下が提供されます。

  • .list()
  • .retrieve()
  • .create()
  • .update()
  • .partial_update()
  • .destroy()
スポンサーリンク

URLの追加

APIを呼び出すためのURLを追加します。
ViewSetをルーターに登録します。

products/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ProductViewSet

router = DefaultRouter()
router.register('products', ProductViewSet)

urlpatterns = [
    path('', include(router.urls)),
]

サイトのurls.pyに追加します。
パスは任意で指定していただければと思いますが、「products/」としました

djangoApiApp/urls.py
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('admin/', admin.site.urls),

    # API追加
    path('products/', include('products.urls')),
]

APIの確認

API画面

起動していない場合は、以下のコマンドで開発サーバーを起動します。

$ python manage.py runserver

以下のURLにアクセスします。

http://localhost:8000/products/

APIを操作するための画面が表示されました。

この画面でAPIの確認ができますので便利です。

curlコマンドなどでアクセスすると分かりますが、実際に使用する際はJSON形式のデータが取得できます。

curl http://localhost:8000/products/
{"products":"http://localhost:8000/products/products/"}

データ編集

一覧を表示するためのURLにアクセスします。

http://localhost:8000/products/products/

一覧のデータと、新規登録を行うためのフォームが表示されました。
このフォームからデータが追加できることを確認しましょう。

詳細を表示するためのURLにアクセスします。(IDを指定)

http://localhost:8000/products/products/1/

詳細画面が開かれ、データの編集や削除などを行うことができます。

これらの画面で操作できることが、APIでも同様にできます。

最低限の実装で、一覧、詳細、新規登録、編集、削除の処理を行うAPIの実装ができました。

ViewSetについて

ReadOnlyModelViewSet

ViewSetは色々ありますが、試しに読み込み専用のReadOnlyModelViewSetを使用してみます。
ModelViewSetと違い、データの編集を行わず参照のみの場合に使用します。

products/views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer


class ProductViewSet(viewsets.ReadOnlyModelViewSet):

    queryset = Product.objects.all()
    serializer_class = ProductSerializer

詳細を表示するためのURLにアクセスします。(IDを指定)

http://localhost:8000/products/products/1/

詳細画面が開かれますが、読み込み専用のためデータの編集や削除を行うことができなくなりました。

ReadOnlyModelViewSetは、以下が提供されます。

  • .list()
  • .retrieve()

APIView

モデルに紐づかないようなビューを作成することもできます。
APIViewクラスを使用して実装します。

試しにダミーデータを返却するようなAPIを実装します。

products/views.py
from rest_framework.views import APIView
from rest_framework.response import Response

...

class ProductDummyApiView(APIView):

    def get(self, request, format=None):
        # ダミーデータを返却
        return Response({"name": "DUMMY!"})

APIViewを継承したクラスでは、get、または、postメソッドを定義します。
HTTPのGETでアクセスした場合は、getメソッドが呼ばれます。

URLを追加します。(追加の行)

products/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
# 追加
from .views import ProductViewSet, ProductDummyApiView

router = DefaultRouter()
router.register('products', ProductViewSet)

urlpatterns = [
    path('', include(router.urls)),

    # 追加
    path("dummy/", ProductDummyApiView.as_view()),
]

以下のURLにアクセスします。

http://localhost:8000/products/dummy/

想定通り、ダミーデータを取得できました。

api_view

関数ベースのapi_viewも確認しましょう。
試しにモデルのデータ一覧を表示する処理を実装します。

products/views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response

...

@api_view(['GET'])
def product_list(request):

    if request.method == 'GET':
        products = Product.objects.all()
        serializer = ProductSerializer(products, many=True)
        return Response(serializer.data)

ModelViewSetのように、モデルとシリアライザーを使用して、一覧を返却する処理にしました。

URLを追加します。(追加の行)

products/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
# 追加
from .views import ProductViewSet, ProductDummyApiView, product_list

router = DefaultRouter()
router.register('products', ProductViewSet)

urlpatterns = [
    path('', include(router.urls)),
    path("dummy/", ProductDummyApiView.as_view()),

    # 追加
    path('list/', product_list),
]

以下のURLにアクセスします。

http://localhost:8000/products/list/

想定通り、商品の一覧を取得できました。

方法は様々ですが、簡単に実装できますので便利です。
また、他にも機能がありますが、公式サイトのドキュメントをご確認ください。

その他

外部サーバーへ公開

作成したアプリは公開して使ってもらいましょう!
Djangoアプリケーションを外部公開する方法をまとめました。

脆弱性対策

脆弱性を抱えたアプリケーションの場合、攻撃を受ける可能性があり大変危険です。
作成したアプリケーションは、脆弱性対策も意識しましょう。

GitHubと連携

GitHubと連携する方法を解説しました。
プロジェクトの管理はGitHubを活用しましょう。

さいごに

今回はDjango REST Frameworkを利用して、RESTfulなAPIを作成してみました。
APIを簡単に実装できますし、画面を通じて確認を行うことができます。
バックエンドのAPIを作る際に、参考にしてみてください。

他にも私のブログで、Djangoについて解説している記事がありますのでご覧ください。

\オススメ/

コメント

タイトルとURLをコピーしました