何をやるのか
前々回の記事と前回の記事で、snippet_list の一覧の API を CSRF_EXEMPT と API_VIEW で GET/POST できるようにした。
今回は snippet_detail の詳細の API を CSRF検証を無効化して作成する
snippets/urls に snippet_detail のルーティングを追加
urlpatterns = [
path('snippets/', views.snippet_list),
path('snippets/<int:pk>/', views.snippet_detail),
]
snippets/1 や snippets/99 のパスにアクセスした時に見るところを
views の snippet_detail に設定する
snippets/views に snippet_detail を記載
@csrf_exempt
def snippet_detail(request, pk):
"""
Retrieve, update or delete a code snippet.
"""
try:
snippet = Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
return HttpResponse(status=404)
if request.method == 'GET':
serializer = SnippetSerializer(snippet)
return JsonResponse(serializer.data)
elif request.method == 'PUT':
data = JSONParser().parse(request)
serializer = SnippetSerializer(snippet, data=data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data)
return JsonResponse(serializer.errors, status=400)
elif request.method == 'DELETE':
snippet.delete()
return HttpResponse(status=204)
モデルからのオブジェクトの取り出し、
GET/PUT/DELETE の JSON レスポンスへの処理
これらを書いている
一つ一つ見ていく
CSRF 検証無効化と request と pk
@csrf_exempt
def snippet_detail(request, pk):
最初に CSRF 検証無視を記載
request と pk を受け取る
primary key, つまり id
Snippet モデルからオブジェクトを取得、例外処理
try:
snippet = Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
return HttpResponse(status=404)
受け取った pk からデータを取り、変数 snippet に入れる
それがなくて失敗したら、404 を返す
GET
if request.method == 'GET':
serializer = SnippetSerializer(snippet)
return JsonResponse(serializer.data)
GET の時は普通にモデルから取り出したデータを
シリアライズして JSON レスポンスで返す
PUT
elif request.method == 'PUT':
data = JSONParser().parse(request)
serializer = SnippetSerializer(snippet, data=data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data)
return JsonResponse(serializer.errors, status=400)
PUT の時は request の中身を JSON パーサーにかけて
シリアライザにかけて、中身があれば JSON レスポンスで返す。
DELETE
elif request.method == 'DELETE':
snippet.delete()
return HttpResponse(status=204)
DELETE の時は単に取ってきたオブジェクトに .delete() をかけて
レスポンスの 404 を返している
POST は存在しない。
snippet_detail では既にあるものにアクセスしてるからだ。
Postman で動作確認
http://localhost:8002/snippets/2/
に Postman で GET アクセスすると
"GET /snippets/2/ HTTP/1.1" 200 120
{
"id": 2,
"title": "",
"code": "print(\"hello, world\")\n",
"linenos": false,
"language": "python",
"style": "friendly"
}
id 2 の データが無事に帰ってきた
次に同じ URL に PUT で HTTP Body に
title を Detail PUT Test に変えた JSON を渡すと
"PUT /snippets/2/ HTTP/1.1" 200 128
{
"id": 2,
"title": "Detail PUT Test",
"code": "print(\"updated\")",
"linenos": false,
"language": "python",
"style": "friendly"
}
ちゃんと update されたものが返ってきた
最後に /
をつけないと
500 internal server error が出るので注意
また、DELETE を送ると
"DELETE /snippets/2/ HTTP/1.1" 204 0
無事に削除された。
まとめ
snippet_detail では
Snippet モデルから渡された id(pk) のデータをとって
なかった場合は 404 を返して
GET の場合はシリアライズして JSON で返す
PUT の場合は JSON パーサーしてシリアライズに成功すれば保存
失敗すれば 400 でエラーを返す
DELETE の場合は delete() をかけて 204 を返す
これで詳細ページの API が作れた
Top comments (0)