Django REST FRAMEWORK Tutorial 6 -- シリアライザを views に組み込んで JSON で GET/POST できるようにする
Tags: django
Published: 2022-04-18 20:08:34


## 何をするのか

https://www.django-rest-framework.org/tutorial/1-serialization/#writing-regular-django-views-using-our-serializer

```py
from django.shortcuts import render

# Create your views here.

```

この状態の何も書いていない views で Snippet シリアライザを読み込むようにする

---

## views に REST のためのライブラリをインポート

```py
from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.parsers import JSONParser
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
```

HTTP レスポンス、JSON レスポンス

https://www.ipa.go.jp/security/vuln/vuln_contents/csrf.html

CSRF(上記のサイトの説明のように勝手にユーザーを操作する)を

https://djangobrothers.com/blogs/django_csrf/#CSRF%E6%A4%9C%E8%A8%BC%E3%82%92%E7%84%A1%E5%8A%B9%E5%8C%96%E3%81%99%E3%82%8B%E4%BE%8B

(REST は外部から叩かれるものなので) 許可するためのライブラリ

JSON のパーサー

Snippet モデル

Snippet シリアライザ

上記をインポートする

---

## snippet_list で GET と POST の API を作る

```py
@csrf_exempt
def snippet_list(request):
    """
    List all code snippets, or create a new snippet.
    """
    if request.method == 'GET':
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return JsonResponse(serializer.data, safe=False)

    elif request.method == 'POST':
        data = JSONParser().parse(request)
        serializer = SnippetSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse(serializer.errors, status=400)
```

csrf_exempt で　CSRF の対策を無効化して

GET の時には単純に Snippet モデルからシリアライズして JSON で返す

POST の時には request からデータを取ってきて JSON にして
シリアライズして、エラーが出なければ保存している

---

## projectName/urls.py の root に snippets の urls をリンクさせる

```py
from django.urls import path, include

urlpatterns = [
    path('', include('snippets.urls')),
]
```

root に snippets アプリの urls が通るようにする

---

## snippets/urls.py に snippet_list を追加

```py
from django.urls import path
from snippets import views

urlpatterns = [
    path('snippets/', views.snippet_list),
]
```

snippet の views をインポートして
snippets/ に views の snippet_list をリンクさせる

---

## ブラウザで root/snippets/ を確認

localhost:8002/snippets/ をブラウザで確認すると

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zlj4moa1kjyj4bipzpmb.png)

```json
[{"id": 1, "title": "", "code": "foo = \"bar\"\n", "linenos": false, "language": "python", "style": "friendly"}, {"id": 2, "title": "", "code": "print(\"hello, world\")\n", "linenos": false, "language": "python", "style": "friendly"}, 
```

JSON でデータの中身が全て返ってきているのを確認できた。

---

## Postman で localhost:8002/snippets/ に GET を送る

Postman というアプリで HTTP の GET や POST ができる

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g1ypu8mzgq9z094az93p.png)

```json
[
    {
        "id": 1,
        "title": "",
        "code": "foo = \"bar\"\n",
        "linenos": false,
        "language": "python",
        "style": "friendly"
    },
    {
        "id": 2,
        "title": "",
        "code": "print(\"hello, world\")\n",
        "linenos": false,
        "language": "python",
        "style": "friendly"
    },
]
```

JSON が綺麗に整形されて出力された。

---

## Postman で POST を送る


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2xu87gklqm7moqugolr8.png)

> web_1  | Bad Request: /snippets/
> web_1  | [19/Apr/2022 08:38:22] "POST /snippets/ HTTP/1.1" 400 76

```json
{
    "non_field_errors": [
        "Invalid data. Expected a dictionary, but got list."
    ]
}
```

何が悪いか教えてくれる。

[ ] で囲っているのがダメだった

```json
    {
        "id": 6,
        "title": "postman test",
        "code": "print(\"hello, world\")\n",
        "linenos": false,
        "language": "python",
        "style": "friendly"
    }
```

普通のオブジェクトで渡せば成功した


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jwrqgdpixe3uhn7vj178.png)

GET で再度取得すると id:6 も追加されていた。

## PUT は失敗した

id 1 で POST すれば update が動くと思いきや、id 7 で作成された
PUT するとエラーになった。
まだ PUT/UPDATE はできないようだ。

シリアライザでは update はあるが、views.py では GET/POST までしか造られていないからだ

---

## まとめ

view で csrf_exempt をつけて
def snippet_list　と定義して GET の時に
モデルのテーブルの中身をシリアライズして JSON にして返す関数を作り

projectName/urls で snippet の url をセットして

snippets/urls で snippets/ に view の snippet_list をセットすると

localhost で snippets/ にアクセスした時に
JSON でモデルの snippets テーブルの中身が全て返ってくるようになる。

Postman を使うと GET で綺麗に JSON が表示されて
POST で JSON オブジェクトを渡すこともできる。