何が変わるのか
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':
@api_view
の後に def で snippet_list で関数を作って
request.method によって if で分岐して処理していた。
class SnippetList(APIView):
def get(self, request, format=None):
def post(self, request, format=None):
これを SnippetList という class を作って
get, post のメソッドごとに 関数を作る構成にする
こうすることで、全体を指すものはクラス、各自メソッドを指すものは関数
と分けることができるのでコードが見やすくなると推測する。
また、get_object を関数にして各メソッドから呼び出すようにすることで
コードの可読性が良くなると推測する。
SnippetList のコードを書いていく
api_view の書き換えと Class SnippetList の全体像
from rest_framework.decorators import api_view
今まで関数の前に使っていた api_view から
from rest_framework.views import APIView
クラスの引数として用いる APIView に変更
class SnippetList(APIView):
def get(self, request, format=None):
def post(self, request, format=None):
こうして 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):
このように、SnippetDetail クラスの中に
関数を作っていく。
get_object の用途
以前は def snippet_detail 直下で
try:
snippet = Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
最初に try で snippet 変数に取ってきておいて
if request.method == 'GET':
serializer = SnippetSerializer(snippet)
return Response(serializer.data)
各メソッドでは、その snippet を使うようにしていた。
これを今回は
def get_object(self, pk):
try:
return Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
raise Http404
オブジェクトを取ってくる一つの関数 get_object に切り出して
def get(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet)
return Response(serializer.data)
各メソッド関数で self から self.get_object として 使用する。
JavaScript の this のようなものだと解釈する。
get_object を実際に書く
from django.http import Http404
Http404 を使うので import して
def get_object(self, pk):
try:
return Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
raise Http404
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)
全てのメソッド関数で self から get_object を使って
現在の primary key のオブジェクトを取ってくるようにする。
urls に クラス名を適用して .as_view() もつける。
snippets/urls.py を見ると
urlpatterns = [
path('snippets/', views.snippet_list),
path('snippets/<int:pk>/', views.snippet_detail),
]
以前は views. snippet_list になっていたが
class と APIView を使うとこれでは読み込めない。
path('snippets/', views.SnippetList.as_view()),
path('snippets/<int:pk>/', views.SnippetDetail.as_view()),
views. の後に SnippetList, SnippetDetail と
CamelCase に直したクラス名を記述して
.as_view() をつける。
これでクラスベースで読み込まれるようになった。
Top comments (0)