DjangoとVue.jsで作るWEBアプリ(その3: API実装編)

Python,TIPS,Vue.jsDjango,Vuetify

一番最初の記事でプロジェクトの設定を行い、前回の投稿で認証機能を作成しました。




今回は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には以下のオプションが用意されています。

  1. CreateAPIView:
    新レコードを作成するためのAPIリクエストです。
    JSON形式のデータを含ませたPOSTリクエストである必要があります。
  2. ListAPIView:
    Modelからレコードを一覧取得するためのAPIリクエストです。
    GETリクエストである必要があります。
  3. RetrieveAPIView:
    Modelから特定のレコードを取得するためのAPIリクエストです。
    GETリクエストである必要があり、レコードのID(主キー)はURLで指定する必要があります。
  4. DestroyAPIView:
    Modelから特定のレコードを削除するためのAPIリクエストです。
    DELETEリクエストである必要があり、レコードのID(主キー)はURLで指定する必要があります。
  5. UpdateAPIView:
    Modelの特定のレコードを更新するためのAPIリクエストです。
    PUTリクエストである必要があり、レコードのID(主キー)はURLで指定する必要があります。
    また、データをJSON形式で含めます。
  6. ListCreateAPIView:
    これは1と2を組み合わせたAPIリクエストです。
    リクエストがPOSTの場合はCreateAPIViewと解釈され、GETの場合はListAPIViewとして解釈されます。
  7. RetrieveUpdateAPIView:
    これは3と5を組み合わせたAPIリクエストです。
    リクエストがGETの場合はRetrieveAPIViewとして解釈され、PUTの場合はUpdateAPIViewとして解釈されます。
  8. RetrieveDestroyAPIView:
    これは3と4を組み合わせたAPIリクエストです。
    どちらもURLでレコードのID(主キー)指定が必要です。
    リクエストがGETの場合はRetrieveAPIViewとして解釈され、DELETEの場合はDestroyAPIViewとして解釈されます。
  9. 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と半角スペースを入力してからトークンを貼り付けます。

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で送信します。

create-userに関しても認証情報が必要なので忘れずに!

うまく作成されましたね。

まとめ

一旦ここまでの進捗をGitHubにアップロードしました。
次回はフロントエンドを実装していき、今回作成したAPIと接続していきます。

Python,TIPS,Vue.jsDjango,Vuetify

Posted by Kenny