DEV Community

kaede
kaede

Posted on

Django REST FRAMEWORK Tutorial 8 -- snippet_detail の GET/PUT/DELTE を csrf_exempt で作成する

何をやるのか

前々回の記事と前回の記事で、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),
]
Enter fullscreen mode Exit fullscreen mode

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

モデルからのオブジェクトの取り出し、
GET/PUT/DELETE の JSON レスポンスへの処理
これらを書いている
一つ一つ見ていく


CSRF 検証無効化と request と pk

@csrf_exempt
def snippet_detail(request, pk):
Enter fullscreen mode Exit fullscreen mode

最初に CSRF 検証無視を記載
request と pk を受け取る
primary key, つまり id


Snippet モデルからオブジェクトを取得、例外処理

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

受け取った pk からデータを取り、変数 snippet に入れる
それがなくて失敗したら、404 を返す

GET

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

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

PUT の時は request の中身を JSON パーサーにかけて
シリアライザにかけて、中身があれば JSON レスポンスで返す。


DELETE

    elif request.method == 'DELETE':
        snippet.delete()
        return HttpResponse(status=204)
Enter fullscreen mode Exit fullscreen mode

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

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

ちゃんと 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)