スポンサーリンク

【その4】チュートリアルから学ぶDjangoRESTframework

【その4】チュートリアルから学ぶDjangoRESTframework

前回はフォーマットを指定してリクエストを処理する方法について「DjangoRESTframework」の使い方を学んでいきました。
今回は、公式ドキュメントのチュートリアルに沿って「 Tutorial 3: Class-based Views」について解説していきたいと思います。
チュートリアルを簡単に日本語訳したものになりますので、英語に抵抗がない方は公式ドキュメントを参考にすることをお勧めします。
本記事の目的は「DjangoRESTframework」の入門編として読み物的な感じで読んでいただけますと幸いです。

クラスベースのViewに書き直す

前回までは関数ベースでViews.pyを書いていたので、今回はそれをクラスベースに書き直していきたいと思います。
普段Djangoを使って開発している方であれば馴染みのある文法ですね。

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status


class SnippetList(APIView):
    """
    スニペットの一覧の取得と、新規スニペットの追加
    """
    def get(self, request, format=None):
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = SnippetSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class SnippetDetail(APIView):
    """
    スニペットの取得・更新・削除
    """
    def get_object(self, pk):
        try:
            return Snippet.objects.get(pk=pk)
        except Snippet.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        snippet = self.get_object(pk)
        serializer = SnippetSerializer(snippet)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        snippet = self.get_object(pk)
        serializer = SnippetSerializer(snippet, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        snippet = self.get_object(pk)
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

views.pyを書き換えたのでurls.pyもそれに合わせて書き換えていきましょう。

from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views

urlpatterns = [
    path('snippets/', views.SnippetList.as_view()),
    path('snippets/<int:pk>/', views.SnippetDetail.as_view()),
]

urlpatterns = format_suffix_patterns(urlpatterns)

これで、準備できましたので前回と同じように動作させることができます。
準備はできたのですが、このような基本的な挙動のクラスであれば、他の方法でも実装することができますのでそちらも紹介していきます。

Mixinクラスを利用して実装

動作は先程と全く同じ動作をするので細かい説明は省いてサンプルコードのみ紹介していきます。

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import mixins
from rest_framework import generics


class SnippetList(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  generics.GenericAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class SnippetDetail(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    generics.GenericAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

先程のコードよりスッキリしてコードも直感的になりましたね。

【おすすめ】genericクラスを利用して実装

個人的には先程紹介したMixinクラスが読みやすくて好きですが、慣れてくるとちょっとくどいのでこれから紹介するgenericクラスで実装するのが簡単でおすすめです。

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import generics


class SnippetList(generics.ListCreateAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer


class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

今まで紹介してきたサンプルコードの中で一番短くてスッキリしましたね。
基本的なAPIであればこれで事足りますが、リクエストを受けたら少し処理を追加したいという場合は、処理を追加したい箇所の関数をオーバーライドしてください。

まとめ

今回はクラスベースでAPIを実装してきました。
いくつかの方法を紹介いたしましたので、開発したいものに合わせて使い分けてみてください。
出力結果は前回と全く同じです。
次回は、認証についてまとめていきたいと思います。

コメント