DjangoとVue.jsで作るWEBアプリ(その3: API実装編)
一番最初の記事でプロジェクトの設定を行い、前回の投稿で認証機能を作成しました。
今回はAPIエンドポイントを実装していきます。
動作確認を行う際にPostmanやInsomniaといったREST APIクライアントを使用しますのでお好きな物をダウンロードしておいて下さい。
勿論、慣れていればcURL等でも問題ありません。
Loginテストをやってみる
前回の最後でログインに成功しました。 ユーザー名とパスワードを入力するとdjangorestframework-jwtによってトークンが割り振られます。
これを試してみましょう。
Postman(もしくはInsomnia)を使用して http://localhost:8000/auth/ にPOSTしてみましょう。
リクエストを送信するとトークンがレスポンスで返されていることが改めて確認できました。
このトークンは認証する際に使用されます。
Serializerの作成
APIエンドポイントを作成するために引き続きDjango REST frameworkを使用していきます。
前回作成したHedgeHogアプリのModelsからアイテムを作成, 更新, 読み取り, 削除するためのエンドポイントを作成しましょう。
それぞれのclassに対してSerializerを作成します。
Serializerは基本的にModelのデータ構造として機能します。 このデータ構造によってデータの投稿方法と取得方法が決まります。
まずはhedgehogフォルダにファイルを作成し、serializers.pyという名前を付け以下のようにします。
server/hedgehog/serializers.py
from django.contrib.auth.models import User
from .models import PileColor, HedgeHog, Comment
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
""" A serializer class for the User model """
class Meta:
model = User
fields = ('id', 'first_name', 'last_name', 'username',
'password', 'is_active', 'is_superuser')
class PileColorSerializer(serializers.ModelSerializer):
""" A serializer for the PileColor model """
class Meta:
model = PileColor
fields = ('id', 'name', 'description')
class HedgeHogSerializer(serializers.ModelSerializer):
""" A serializer for the HedgeHog Model """
class Meta:
model = HedgeHog
fields = ('id', 'name', 'pile_color', 'stars', 'description', 'created')
class CommentSerializer(serializers.ModelSerializer):
""" Serializer for the Comment model """
class Meta:
model = Comment
fields = ('id', 'user', 'hedgehog', 'comment', 'visible', 'created')
Viewsの作成
Serializerを作成したら次にViewを作成していきます。
このViewによってAPIリクエストを可能にします。
hedgehog/views.py
from django.contrib.auth.models import User
from rest_framework import generics, permissions
from .models import PileColor, HedgeHog, Comment
from .serializers import UserSerializer, PileColorSerializer, HedgeHogSerializer, CommentSerializer
genericsには各Viewで何をしようとしているのかを決定するクラスが含まれています。
例えばレコードの一覧表示、新レコードの作成やレコードの削除などです。
permissionsをインポートすることで次の操作を実行するために必要なパーミッションを指定できます。
例えば新ユーザーを追加できるのは管理者のみでログイン中のユーザーだけがHedgeHogの表示やコメント追加を行える、といった感じです。
そしてModelごとに1つ以上のViewを作成でき、genericsには以下のオプションが用意されています。
- CreateAPIView:
新レコードを作成するためのAPIリクエストです。
JSON形式のデータを含ませたPOSTリクエストである必要があります。
- ListAPIView:
Modelからレコードを一覧取得するためのAPIリクエストです。
GETリクエストである必要があります。
- RetrieveAPIView:
Modelから特定のレコードを取得するためのAPIリクエストです。
GETリクエストである必要があり、レコードのID(主キー)はURLで指定する必要があります。
- DestroyAPIView:
Modelから特定のレコードを削除するためのAPIリクエストです。
DELETEリクエストである必要があり、レコードのID(主キー)はURLで指定する必要があります。
- UpdateAPIView:
Modelの特定のレコードを更新するためのAPIリクエストです。
PUTリクエストである必要があり、レコードのID(主キー)はURLで指定する必要があります。
また、データをJSON形式で含めます。
- ListCreateAPIView:
これは1と2を組み合わせたAPIリクエストです。
リクエストがPOSTの場合はCreateAPIViewと解釈され、GETの場合はListAPIViewとして解釈されます。
- RetrieveUpdateAPIView:
これは3と5を組み合わせたAPIリクエストです。
リクエストがGETの場合はRetrieveAPIViewとして解釈され、PUTの場合はUpdateAPIViewとして解釈されます。
- RetrieveDestroyAPIView:
これは3と4を組み合わせたAPIリクエストです。
どちらもURLでレコードのID(主キー)指定が必要です。
リクエストがGETの場合はRetrieveAPIViewとして解釈され、DELETEの場合はDestroyAPIViewとして解釈されます。
- RetrieveUpdateDestroyAPIView:
これは3と4及び5を組み合わせたAPIリクエストです。
リクエストがGETの場合はRetrieveAPIViewとして解釈され、PUTの場合はUpdateAPIView、DELETEの場合はDestroyAPIViewとして解釈されます。
殆どの場合は6と9の2種類で対応できます。
但し、レコードを削除することはお勧めしないので実際には6と7を使用するのが安全です。
それではUsersModelのためのViewを作成していきます。
server/hedgehog/views.py
from django.contrib.auth.models import User
from rest_framework import generics, permissions
from .models import PileColor, HedgeHog, Comment
from .serializers import UserSerializer, PileColorSerializer, HedgeHogSerializer, CommentSerializer
class UserList(generics.ListAPIView):
""" View to list all users"""
queryset = User.objects.all().order_by('first_name')
serializer_class = UserSerializer
permission_classes = (permissions.IsAuthenticated,)
class UserCreate(generics.CreateAPIView):
""" View to create a new user. Only accepts POST requests """
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (permissions.IsAdminUser, )
class UserRetrieveUpdate(generics.RetrieveUpdateAPIView):
""" Retrieve a user or update user information.
Accepts GET and PUT requests and the record id must be provided in the request """
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (permissions.IsAuthenticated, )
3つのクラスベースViewを作成しました。
まずはUserをリストするためのものでログインしたユーザーのみがリストを見ることが出来ます。
次に2つ目のものは管理者ユーザー(is_superuserがTrueであるユーザー)だけが新しいユーザーアカウントを作成することを許可しています。
最後のViewは特定のユーザー情報を取得したり更新するためのものです。
これを他のModelでも作成していきます。
class PileColorListCreate(generics.ListCreateAPIView):
""" List and create PileColors """
queryset = PileColor.objects.all()
serializer_class = PileColorSerializer
permission_classes = (permissions.IsAuthenticated, )
class PileColorRetrieveUpdate(generics.RetrieveUpdateAPIView):
""" Retrieve and update PileColor information """
queryset = PileColor.objects.all()
serializer_class = PileColorSerializer
permission_classes = (permissions.IsAuthenticated, )
class HedgeHogListCreate(generics.ListCreateAPIView):
"""List and create HedgeHogs """
queryset = HedgeHog.objects.all().order_by('name')
serializer_class = HedgeHogSerializer
permission_classes = (permissions.IsAuthenticated, )
class HedgeHogRetrieveUpdate(generics.RetrieveUpdateAPIView):
"""Retrieve and update a HedgeHog"""
queryset = HedgeHog.objects.all()
serializer_class = HedgeHogSerializer
permission_classes = (permissions.IsAuthenticated, )
class CommentListCreate(generics.ListCreateAPIView):
""" List or create a HedgeHog """
queryset = Comment.objects.all()
serializer_class = CommentSerializer
permission_classes = (permissions.IsAuthenticated, )
class CommentRetrieveUpdate(generics.RetrieveUpdateAPIView):
""" List or create a HedgeHog """
queryset = Comment.objects.all()
serializer_class = CommentSerializer
permission_classes = (permissions.IsAuthenticated, )
続いてViewごとにAPIエンドポイントを作成していきます。
これがフロントエンドからのAPIのやりとりになります。
hedgehog/urls.py
from django.urls import path
from .views import *
urlpatterns = [
path('users/', UserList.as_view()),
path('create-users/', UserCreate.as_view()),
path('users/<pk>/', UserRetrieveUpdate.as_view()),
path('pilecolors/', PileColorListCreate.as_view()),
path('pilecolors/<pk>/', PileColorRetrieveUpdate.as_view()),
path('hedgehogs/', HedgeHogListCreate.as_view()),
path('hedgehogs/<pk>/', HedgeHogRetrieveUpdate.as_view()),
path('comments/', CommentListCreate.as_view()),
path('comments/<pk>/', CommentRetrieveUpdate.as_view())
]
最後にプロジェクトルートにhedgehogアプリへ誘導するよう登録します。
server/urls.py
from django.contrib import admin
from django.urls import include, path # includeを追加
from django.conf.urls import include
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
path('admin/', admin.site.urls),
path('auth/', obtain_jwt_token),
path('api/', include('hedgehog.urls')) # 追加
]
これで準備OKです。
早速エンドポイントのテストをしていきます。
Postmanを使用して http://localhost:8000/api/users/ に送信してみましょう!
エラーが帰ってきてしまいました。。。
これはUSerListクラスにIsAuthenticatedを付与しているためです。
リクエストを成功させるにはまずログインを行い、トークンを含ませてやる必要があります。
それではまず、Postmanの[Heders]タブを開き [KEY] で Authorization を選択し [VALUE] にJWTと半角スペースを入力してからトークンを貼り付けます。
トークンの設定が完了したら改めてリクエストを送ってみましょう。
今度は無事にレスポンスが帰りました!
次はこの管理者情報を更新してみましょう。
同じトークンを使用してPUTリクエストを作成します。
先ほどのレスポンスで帰ってきたJSONをコピーしBodyに貼り付けて適当に値を変更してください。
先頭の “id" についてはパラメータに含ませる必要があるためJSONから消し込みます。
{
"first_name": "hedge",
"last_name": "hog",
"username": "kenny",
"password": "pbkdf2_sha256$150000$0MQB13jKx8m5$dcQmZUEQR4jjuczVdRusg2gFZeYjBpgoqDwGkSkZvI4=",
"is_active": true,
"is_superuser": true
}
今回は"first_name" と “last_name" を変更してみました。
向き先URLに “id" の値を追加し送信しましょう。
新しいユーザーを作成する場合は向き先UELをcreate-userに変更し、POSTで送信します。
うまく作成されましたね。
まとめ
一旦ここまでの進捗をGitHubにアップロードしました。
次回はフロントエンドを実装していき、今回作成したAPIと接続していきます。