はじめに
今回はDjango REST Frameworkを利用して、RESTfulなAPIを作成してみます。
Djangoの環境とプロジェクトの作成方法は以下をご覧ください。
また、今回はデータベースにMySQLを使用しますので、以下を参考に環境を構築してください。
他にも私のブログで、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コンテナで作業していますので、以下のファイルを修正します。
一番最後の行を追加します。
FROM python:3
ENV PYTHONUNBUFFERED 1
RUN pip install django
RUN pip install mysqlclient
RUN pip install djangorestframework
F1キーをクリックし、コンテナをリビルドします。(Dev 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 .
Djangoのデータベースの設定を変更します。
デフォルトでsqlite3が指定されていますが、MySQLに変更します。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django_sample',
'USER': 'root',
'PASSWORD': 'password',
'HOST': 'db',
'PORT': '3306',
}
}
以下の項目も修正します。(言語とタイムゾーンの修正)
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
設定ファイルについては、SECRET_KEYやデータベースの接続情報などの機密情報が含まれます。
GitHubの公開リポジトリなどに、そのままプッシュしてしまうのは危険です。
今回は割愛しますが、以下の記事も参考にしてください。
アプリ追加と設定
追加
以下のコマンドで、Djangoプロジェクトにアプリを追加します。
商品マスターを想定したアプリで、APIの実装を行います。
$ python manage.py startapp products
設定の修正
サイトのsettings.pyに、アプリを追加します。
INSTALLED_APPS = [
...
'rest_framework',
'products',
]
モデルとテーブルの作成
モデルの作成
テーブル定義に合わせたモデルを作成します。
商品を想定したモデルを作成しました。
class Product(models.Model):
name = models.CharField(max_length=200)
price = models.IntegerField()
以下のコマンドでマイグレーションファイルを作成します。
$ python manage.py makemigrations products
以下のファイルが自動で作成されます。
# 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/
管理画面が表示されますので、先ほど作成したユーザでログインを行います。
管理画面にアクセスすることができました。
今回テーブルを作成した、商品マスタを編集できるようにします。
以下のファイルを修正します。
from django.contrib import admin
# Register your models here.
from .models import Product
admin.site.register(Product)
画面を更新すると、商品テーブルのマスタメンテが追加になりました。
新規登録などを行うことができます。
一覧を表示すると、「xx object (1)」のように表示されます。
名前が表示されるように、モデルを修正します。
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
画面を更新すると、一覧に名前が表示されるようになりました。
Serializerクラスの作成
APIでデータのやり取りを行うためのシリアライザーを作成します。
以下のファイルを作成します。
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ['name', 'price']
ビューの作成
APIの処理を、ViewSetを使用して実装します。
それにより例えば、一覧や詳細データの取得、新規登録、更新、削除などの処理が使えるようになります。
ここではModelViewSetを使用して、以下のように実装します。
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
URLの追加
APIを呼び出すためのURLを追加します。
ViewSetをルーターに登録します。
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/」としました。
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を操作するための画面が表示されました。
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の実装ができました。
ViewSetについて
ReadOnlyModelViewSet
ViewSetは色々ありますが、試しに読み込み専用のReadOnlyModelViewSetを使用してみます。
ModelViewSetと違い、データの編集を行わず参照のみの場合に使用します。
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/
詳細画面が開かれますが、読み込み専用のためデータの編集や削除を行うことができなくなりました。
APIView
モデルに紐づかないようなビューを作成することもできます。
APIViewクラスを使用して実装します。
試しにダミーデータを返却するようなAPIを実装します。
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!"})
URLを追加します。(追加の行)
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も確認しましょう。
試しにモデルのデータ一覧を表示する処理を実装します。
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)
URLを追加します。(追加の行)
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を活用しましょう。
GitHub Copilot
GitHub Copilotを導入し、AIにコーディングをサポートしてもらうこともできます。
さいごに
今回はDjango REST Frameworkを利用して、RESTfulなAPIを作成してみました。
APIを簡単に実装できますし、画面を通じて確認を行うことができます。
バックエンドのAPIを作る際に、参考にしてみてください。
他にも私のブログで、Djangoについて解説している記事がありますのでご覧ください。
コメント