Django REST FrameworkでAPIを作成してみた
背景
以前からDjangoにおけるWebアプリケーション作成において、ReactやFlutterなどのフロントエンドのフレームワークとの結合を考えております。
今回は、それに先立ちフロントエンドとバックエンドとのやりとりをDjango REST Frameworkを利用したRESTful APIで行なうために学習した記録です。
先人たちの知恵をお借りするなどして解決できたことを、この場をお借りして感謝するとともに、大変恐縮ですが自分のメモとして、こちらへまとめておきます。
はじめに
チグサさんのブログ:「チグサウェブ」の記事を参考に、Django REST Frameworkを利用して、RESTful APIを作成してみました。
大変分かりやすくまとまっており、これから学習する方にもオススメです。
今回、チグサさんの記事と異なり、dockerでの環境構築やDjangoで利用するデータベースの変更は省いています。
そもそもAPIとは?
Application Programming Interfaceの略。
今回作成するのはHTTPやHTTPS通信でデータのやり取りを行うことができる、Web APIです。
Django REST Frameworkとは?
Django REST Framework (DRF)とはRESTful API開発に特化したDjangoのフレームワークです。
DRFを使うことでよりRESTfulなWebアプリケーションを作成することができます。
RESTful APIとはRESTという原則を守っているHTTP呼び出しインターフェースのことです。
Django REST Frameworkを使用することにより、Djangoフレームワークで簡単にAPIの実装ができる優れもの。
バックエンドのAPIサーバーを実装する際に大変便利です。
1.python仮想環境の構築
Python環境に、venvにより仮想環境を構築します。(すでにPython実行環境は構築済みの前提です。)
以下のコマンドを実行します。
python -m venv venv
venv
├ Include
├ Lib
└ Scripts
pyvenv.cfg
以下のコマンドで仮想環境を有効にします。
cd venv\Scripts
activate.bat
以下のコマンドでpipをupgradeします。
(venv) python -m install --upgrade pip
2.Djangoのインストール
以下のコマンドでdjangoをインストールします。
(venv) pip install django
3.Djangoプロジェクトの作成
以下のコマンドで、Djangoプロジェクトを作成します。
最後に「.」(ドット)を付けることで、同じ階層にプロジェクトファイルを作成しています。
(venv) django-admin startproject djangoApiApp .
venv
├ Include
├ djangoApiApp # 追加
├ __pycache__
├ __init__.py
├ asgi.py
├ settings.py
└ wsgi.py
├ Lib
└ Scripts
db.sqlite3
manage.py
pyvenv.cfg
4.Djangoのデータベースの設定
デフォルトでsqlite3が指定されていますので、今回はこのまま使います。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
言語とタイムゾーンの項目を修正します。
LANGUAGE_CODE = 'ja' # 修正
TIME_ZONE = 'Asia/Tokyo' # 修正
今回は、これらを管理するツールとして便利なdjango-environを使います。
django-environのインストール
django-environは外部モジュールなのでインストールする必要があります。
Djangoアプリケーションが動作しているPython環境で、次のコマンドを実行します。
(venv) pip install django-environ
インストールはこれだけです。
.envファイルの作成と記述
manage.pyと同じ階層(今回の構成ではdjandoプロジェクト直下)に「.env」という名前でファイルを作成します。
venv
├ Include
├ djangoApiApp
├ __pycache__
├ __init__.py
├ asgi.py
├ settings.py
└ wsgi.py
├ Lib
└ Scripts
.env # 追加
db.sqlite3
manage.py
pyvenv.cfg
このファイルに環境変数などの機密情報を分離します。
SECRET_KEY=django-insecure-*************************************
DEBUG=True
DATABASE_ENGINE=django.db.backends.sqlite3 # 使用するDBのエンジン(sqlite3ならdjango.db.backends.sqlite3)
DATABASE_DB=db.sqlite3 # データベース名(sqlite3ならdb.sqlite3)
DATABASE_USER=django_user # defaultのままで可
DATABASE_PASSWORD=password # defaultのままで可
DATABASE_HOST=localhost # defaultのままで可
DATABASE_PORT=5432 # defaultのままで可
=の前後に半角スペースが入ったり、文字列をシングルクォーテーションで囲っていたりするとエラーになるので注意しましょう。
settings.pyで環境変数を呼び出す
.envファイルに環境変数をsettings.pyで呼び出します。
import os # 追加
import environ # 追加
env = environ.Env() # 追加
env.read_env('.env') # 追加
SECRET_KEY = env('SECRET_KEY') # 修正
DEBUG = env('DEBUG') # 修正
DATABASES = {
'default': {
'ENGINE': env.get_value('DATABASE_ENGINE', default='django.db.backends.sqlite3'), # 修正
'NAME': env.get_value('DATABASE_DB', default=os.path.join(BASE_DIR, 'db.sqlite3')), # 修正
'USER': env.get_value('DATABASE_USER', default='django_user'), # 追加
'PASSWORD': env.get_value('DATABASE_PASSWORD', default='password'), # 追加
'HOST': env.get_value('DATABASE_HOST', default='localhost'), # 追加
'PORT': env.get_value('DATABASE_PORT', default='5432'), # 追加
}
}
これだけ!
5.Django REST Frameworkのインストール
Djangoアプリケーションが動作しているPython環境に、Django REST Frameworkをインストールします。
(venv) pip install djangorestframework
6.アプリ追加と設定
以下のコマンドで、Djangoプロジェクトにアプリケーションを追加します。
商品マスターを想定したアプリケーションとして、APIを実装します。
(venv) python manage.py startapp products
venv
├ Include
├ djangoApiApp
├ __pycache__
├ __init__.py
├ asgi.py
├ settings.py
└ wsgi.py
├ Lib
├ products # 追加
├ __pycache__
├ migtarions
├ __init__.py
├ admin.py
├ apps.py
├ models.py
├ tests.py
└ views.py
└ Scripts
.env
db.sqlite3
manage.py
pyvenv.cfg
djangoプロジェクトのsettings.pyに、アプリケーションを追加します。
INSTALLED_APPS = [
...
'rest_framework', # 追加
'products', # 追加
]
7.Modelとテーブルの作成
テーブル定義に合わせたモデルを作成します。
今回は商品を想定したモデルとしました。
# 以下を追加
class Product(models.Model):
name = models.CharField(max_length=200)
price = models.IntegerField()
以下のコマンドでマイグレーションファイルを作成します。
(venv) 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()),
],
),
]
以下のコマンドでマイグレーションを実行し、テーブルを作成します。
(venv) python manage.py migrate
管理画面での確認
Djangoの管理画面から確認してみましょう。
まずは、管理画面にログインするためのユーザを作成します。
以下のコマンドを実行します。
(venv) python manage.py createsuperuser
以下のコマンドで開発サーバーを起動します。
(venv) 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
画面を更新すると、一覧に名前が表示されるようになりました!
8.Serializerクラスの作成
APIでデータのやり取りを行うためのSerializer(シリアライザー)を設定するため、以下のファイルを作成します。
# 以下を追加
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ['name', 'price']
venv
├ Include
├ djangoApiApp
├ __pycache__
├ __init__.py
├ asgi.py
├ settings.py
└ wsgi.py
├ Lib
├ products
├ __pycache__
├ migtarions
├ __init__.py
├ admin.py
├ apps.py
├ models.py
├ serializers.py # 追加
├ tests.py
└ views.py
└ Scripts
.env
db.sqlite3
manage.py
pyvenv.cfg
Django REST Frameworkの最大の特徴はこのSerializerと言っても過言ではありません。
Serializerについては、「Django REST Framework の特徴(Serializer)」のセクションでの説明が参考になります。
9.Viewの作成
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
10.URLの追加
APIを呼び出すためのURLをアプリケーションのurls.pyに追加します。
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)),
]
venv
├ Include
├ djangoApiApp
├ __pycache__
├ __init__.py
├ asgi.py
├ settings.py
└ wsgi.py
├ Lib
├ products
├ __pycache__
├ migtarions
├ __init__.py
├ admin.py
├ apps.py
├ models.py
├ serializers.py
├ tests.py
├ urls.py # 追加
└ views.py
└ Scripts
.env
db.sqlite3
manage.py
pyvenv.cfg
djangoプロジェクトのurls.pyに追加します。
パスは任意で指定できます。今回は「products/」としました。
from django.contrib import admin
from django.urls import path, include # includeを追加
urlpatterns = [
path('admin/', admin.site.urls),
# API
path('products/', include('products.urls')), # 追加
]
11.APIの確認
API画面
起動していない場合は、以下のコマンドで開発サーバーを起動しましょう。
(venv) python manage.py runserver
以下のURLにアクセスします。
http://localhost:8000/products/
APIを操作するための画面が表示されます。
curlコマンドなどでAPIへアクセスすると、実際に使用する際はJSON形式のデータを取得できることが分かります。
(venv) 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が実装できました。
12.ViewSetについて
APIView
Modelに紐づかないようなViewも作成できます。
これは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 # 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により、Modelのデータ一覧を表示する処理の実装例です。
from rest_framework.decorators import api_view # 追加
...
# 以下を追加
@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のように、ModelとSerializerを使用して、一覧を返却する処理にします。
URLを追加します。
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ProductViewSet, ProductDummyApiView, product_list # 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/
商品の一覧を取得できました!
今回のソースコードはGitHubにコミット済みです。
参考
(編集後記)
今回はDjango REST Framework (DRF)を利用して、RESTfulなAPIを作成してみましたが、実装は簡単ですし、画面を通じて確認を行なえるためユーザーフレンドリーです。
バックエンドのAPIを作る際には、選択肢のひとつとしてDRFは大いに利用できるものと分かりました。
ここまでの手順を基に、今後もDjangoによるWebアプリケーション作成をすすめてみます。
皆様の参考になれば幸いです。
今後、フロントエンドにReactまたはFlutterを結合したWebアプリケーションの作成に移りたいのですが、どちらを選ぶかで躊躇している状態でして、両者のメリデメをよく検討した上で決定したいと思います。
Discussion