Django Restframeworkのチュートリアル(2)

# はじめに
Django Restframeworkのチュートリアル(1)では単純にREST APIを作っていただけですが今度はDjango Restframeworkの機能を使ってリファクタリングしていきます。

# Viewのリファクタリング

```python:snippets/views.py
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer


@api_view(['GET', 'POST'])
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 Response(serializer.data)

    elif request.method == 'POST':
        serializer = SnippetSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(['GET', 'POST', 'DELETE'])
def snippet_detail(request, pk):
    """
    Retrieve, update or delete a code snippet.
    """
    try:
        snippet = Snippet.objects.get(pk=pk)
    except Snippet.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

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

    elif request.method == 'PUT':
        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)

    elif request.method == 'DELETE':
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
```

# フォーマットオプションの追加
フォーマットオプションを追加します。viewの関数にformat引数を追加します。

```python:snippets/views.py
def snippet_list(request, format=None):
・・・
def snippet_detail(request, pk, format=None):
```

## urls.pyの変更
```python:snippets/urls.py
from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views

urlpatterns = [
    url(r'^snippets/$', views.snippet_list),
    url(r'^snippets/(?P<pk>[0-9]+)$', views.snippet_detail),
]

urlpatterns = format_suffix_patterns(urlpatterns)
```

# 動作確認
```
$ http http://127.0.0.1:8000/snippets/
HTTP/1.1 200 OK
Allow: GET, OPTIONS, POST
Content-Length: 317
Content-Type: application/json
Date: Tue, 12 Dec 2017 02:56:59 GMT
Server: WSGIServer/0.2 CPython/3.6.3
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN

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

```

```
$ http http://127.0.0.1:8000/snippets/ Accept:application/json  # Request JSON
$ http http://127.0.0.1:8000/snippets/ Accept:text/html         # Request HTML
```

```
$ http http://127.0.0.1:8000/snippets.json  # JSON suffix
$ http http://127.0.0.1:8000/snippets.api   # Browsable API suffix
```

```
$ http --form POST http://127.0.0.1:8000/snippets/ code="print 123"
HTTP/1.1 201 Created
Allow: GET, OPTIONS, POST
Content-Length: 93
Content-Type: application/json
Date: Tue, 12 Dec 2017 02:59:31 GMT
Server: WSGIServer/0.2 CPython/3.6.3
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN

{
    "code": "print 123",
    "id": 4,
    "language": "python",
    "linenos": false,
    "style": "friendly",
    "title": ""
}

$ http --json POST http://127.0.0.1:8000/snippets/ code="print 456"
HTTP/1.1 201 Created
Allow: GET, OPTIONS, POST
Content-Length: 93
Content-Type: application/json
Date: Tue, 12 Dec 2017 02:59:44 GMT
Server: WSGIServer/0.2 CPython/3.6.3
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN

{
    "code": "print 456",
    "id": 5,
    "language": "python",
    "linenos": false,
    "style": "friendly",
    "title": ""
}