DEV Community

kaede
kaede

Posted on

Django REST FRAMEWORK Tutorial 10 -- def snippet_list を Class SnippetList に書き直す

何が変わるのか

https://www.django-rest-framework.org/tutorial/3-class-based-views/

@api_view(['GET', 'POST']) def snippet_list(request, format=None): if request.method == 'GET': elif request.method == 'POST': 
Enter fullscreen mode Exit fullscreen mode

@api_view の後に def で snippet_list で関数を作って
request.method によって if で分岐して処理していた。

class SnippetList(APIView): def get(self, request, format=None): def post(self, request, format=None): 
Enter fullscreen mode Exit fullscreen mode

これを SnippetList という class を作って
get, post のメソッドごとに 関数を作る構成にする


こうすることで、全体を指すものはクラス、各自メソッドを指すものは関数
と分けることができるのでコードが見やすくなると推測する。

また、get_object を関数にして各メソッドから呼び出すようにすることで
コードの可読性が良くなると推測する。



SnippetList のコードを書いていく

api_view の書き換えと Class SnippetList の全体像

from rest_framework.decorators import api_view 
Enter fullscreen mode Exit fullscreen mode

今まで関数の前に使っていた api_view から

from rest_framework.views import APIView 
Enter fullscreen mode Exit fullscreen mode

クラスの引数として用いる APIView に変更

class SnippetList(APIView): def get(self, request, format=None): def post(self, request, format=None): 
Enter fullscreen mode Exit fullscreen mode

こうして class と def で書き直す。
中身はのロジックは以前 if で分岐していた時と全く同じ。



snippet_detail を書き直す

こちらは新たに作成される get_object が依然と大きく異なる。

全体構成

class SnippetDetail(APIView): def get_object(self, pk): def get(self, request, pk, format=None): def put(self, request, pk, format=None): def delete(self, request, pk, format=None): 
Enter fullscreen mode Exit fullscreen mode

このように、SnippetDetail クラスの中に
関数を作っていく。


get_object の用途

以前は def snippet_detail 直下で

 try: snippet = Snippet.objects.get(pk=pk) except Snippet.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) 
Enter fullscreen mode Exit fullscreen mode

最初に try で snippet 変数に取ってきておいて

 if request.method == 'GET': serializer = SnippetSerializer(snippet) return Response(serializer.data) 
Enter fullscreen mode Exit fullscreen mode

各メソッドでは、その snippet を使うようにしていた。

これを今回は

 def get_object(self, pk): try: return Snippet.objects.get(pk=pk) except Snippet.DoesNotExist: raise Http404 
Enter fullscreen mode Exit fullscreen mode

オブジェクトを取ってくる一つの関数 get_object に切り出して

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

各メソッド関数で self から self.get_object として 使用する。
JavaScript の this のようなものだと解釈する。


get_object を実際に書く

from django.http import Http404 
Enter fullscreen mode Exit fullscreen mode

Http404 を使うので import して

 def get_object(self, pk): try: return Snippet.objects.get(pk=pk) except Snippet.DoesNotExist: raise Http404 
Enter fullscreen mode Exit fullscreen mode

get_object では pk に応じてオブジェクトを取得し
なければ Http404 を返す。
別の関数に切り出し Http404 を使う以外は前回と変更点はない。


get, put, delete

 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) 
Enter fullscreen mode Exit fullscreen mode

全てのメソッド関数で self から get_object を使って
現在の primary key のオブジェクトを取ってくるようにする。


urls に クラス名を適用して .as_view() もつける。

snippets/urls.py を見ると

urlpatterns = [ path('snippets/', views.snippet_list), path('snippets/<int:pk>/', views.snippet_detail), ] 
Enter fullscreen mode Exit fullscreen mode

以前は views. snippet_list になっていたが

class と APIView を使うとこれでは読み込めない。

 path('snippets/', views.SnippetList.as_view()), path('snippets/<int:pk>/', views.SnippetDetail.as_view()), 
Enter fullscreen mode Exit fullscreen mode

views. の後に SnippetList, SnippetDetail と
CamelCase に直したクラス名を記述して
.as_view() をつける。

これでクラスベースで読み込まれるようになった。

Top comments (0)