【学習記録】Django REST frameworkチュートリアル14 Viewsets

この記事の続きです。

programming-gogogogo.hatenablog.com

こちらの動画を見ながらPythonDjango REST framework(DRF)について勉強しています。

www.youtube.com

今回はDRFのViewsetsについて勉強します。
公式ドキュメントの説明はこちらです。

https://www.django-rest-framework.org/api-guide/viewsets/#viewsets

ドキュメントの説明を自分は以下のように解釈しました。

Django REST framework allows you to combine the logic for a set of related views in a single class, called a ViewSet. In other frameworks you may also find conceptually similar implementations named something like 'Resources' or 'Controllers'.

DRFでは関連するviewをViewSetというひとつにクラスにまとめることができる。
他のフレームワークでいうところのコントローラやリソースと同じ概念。

A ViewSet class is simply a type of class-based View, that does not provide any method handlers such as .get() or .post(), and instead provides actions such as .list() and .create(). View

ViewSetクラスはクラスが基となるViewで、.get()や.post()メソッドハンドラーは提供しない代わりに、.list()や.create()などのアクションがあるとのこと。

Viewsetを実装するためapi_basic/views.pyにArticleViewsetクラスを追加します。

class ArticleViewSet(viewsets.ViewSet):
    def list(self, request):
        articles = Article.objects.all()
        serializer = ArticleSerializer(articles, many=True)
        return Response(serializer.data)

    def create(self, request):
        serializer = ArticleSerializer(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)

    def retrieve(self, request, pk=None):
        queryset = Article.objects.all()
        article = get_object_or_404(queryset, pk=pk)
        serializer = ArticleSerializer(article)
        return Response(serializer.data)

    def update(self, request, pk=None):
        article = Article.objects.get(pk=pk)
        serializer = ArticleSerializer(article, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

次にapi_basic/urls.pyを以下のようにします。

from django.urls import path, include
from .views import article_list, article_detail, ArticleAPIView, ArticleDetails, GenericAPIView, ArticleViewSet
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register('article', ArticleViewSet, basename='article')


urlpatterns = [
    path('viewset/', include(router.urls)),
    path('viewset/<int:pk>/', include(router.urls)),
    path('article/', ArticleAPIView.as_view()),
    path('detail/<int:id>/', ArticleDetails.as_view()),
    path('generic/article/<int:id>/', GenericAPIView.as_view(),)
]

上記の変更を加えた後にサーバーを再起動して、loalhost:8000/viewset/articleにアクセスするとデータが正常に取得できました。
f:id:JunpeiNakasone:20210326221359p:plain

またlocalhost:8000/viewset/にアクセスするとviewset/配下にあるAPIエンドポイント一覧が表示されるようです。
f:id:JunpeiNakasone:20210326221542p:plain

Createメソッドも実装しているので、管理画面のフォームからPOSTリクエストを送ると正常にデータが追加されました。
f:id:JunpeiNakasone:20210326221844p:plain

f:id:JunpeiNakasone:20210326221910p:plain

urlpatternsでviewset/<int:pk>/のエンドポイントも実装しているので、viewset/article/5/でブラウザにアクセスするとIDが5のデータが取得できます。

f:id:JunpeiNakasone:20210326222855p:plain

またID別に取得した画面ではPUTリクエストを送るフォームがあり、更新処理を行うことができます。
f:id:JunpeiNakasone:20210326223047p:plain f:id:JunpeiNakasone:20210326223103p:plain

Viewsetを使ったCRUDの実装方法が確認できました。