Help us understand the problem. What is going on with this article?

Django REST frameworkチュートリアル その1

More than 1 year has passed since last update.

Tutorial 1: Serialization

Django REST frameworkのチュートリアルをなぞってみます。
翻訳ではなく自分なりに少しアレンジしてますので、詳しい説明などは、公式のチュートリアルを参照しましょう。

準備

まずは仮想環境を作って、アクティベートしましょう。

python -m venv env
source env/bin/activate

django, djangorestframeworkpipでインストールします。

pip install django
pip install djangorestframework

tutorialという名前のプロジェクトを作成して、その中にsnippetsという名前のアプリを作成します。

django-admin startproject tutorial
cd tutorial
python manage.py startapp snippets

rest_frameworksnippetsというアプリを使うことをDjangoに知らせるためにtutorial/settings.pyINSTALLED_APPSに追記します。

tutorial/settings.py
INSTALLED_APPS = (
    ...
    'rest_framework',
    'snippets.apps.SnippetsConfig',
)

models.py

次にテストのために適当なモデルを作成します。

snippets/models.py
from django.db import models


class Snippet(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    title = models.CharField(max_length=100, blank=True, default='')
    code = models.TextField()

    class Meta:
        ordering = ('created',)

チュートリアルにはもっとたくさんフィールドを定義しているのですがあまり本質ではないので省略しました。
データベースのマイグレーションを行います。

python manage.py makemigrations snippets
python manage.py migrate

serializers.py (Serializerクラスの継承)

Snippetモデルをシリアライズ/デシリアライズするためのserializers.pyを作成します。ちなみにシリアライズとは、

シリアライズとは、ソフトウェア内部で扱っているデータをそのまま、保存したり送受信することができるように変換することです。

ということを指すようです。
serializers.pyを作成していきましょう。serializers.pyはデフォルトのファイル群には含まれていないので、新規で作成します。

snippets/serializers.py
from rest_framework import serializers
from snippets.models import Snippet


class SnippetSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    title = serializers.CharField(required=False, allow_blank=True, max_length=100)
    code = serializers.CharField(style={'base_template': 'textarea.html'})

    def create(self, validated_data):
        """
        Create and return a new `Snippet` instance, given the validated data.
        """
        return Snippet.objects.create(**validated_data)

    def update(self, instance, validated_data):
        """
        Update and return an existing `Snippet` instance, given the validated data.
        """
        instance.title = validated_data.get('title', instance.title)
        instance.code = validated_data.get('code', instance.code)
        instance.save()
        return instance

SnippetSerializerSerializerクラスを継承しています。クラス変数にはシリアライズするフィールドを定義します。そして、モデルのインスタンスが作成または更新されるときに呼び出されるcreate()メソッドとupdate()メソッドを定義します。
ここら辺の実装はのちに現れるModelSerializerクラスによって一般的には省略されます。

serializers.py (ModelSerializerクラスの継承)

SnippetSerializerSerializerクラスを継承して作ったばかりですが、早速ModelSerializerを継承して書き換えてみましょう。

snippets/serializers.py
from rest_framework import serializers
from snippets.models import Snippet


class SnippetSerializer(serializers.ModelSerializer):
    class Meta:
        model = Snippet
        fields = ('id', 'title', 'code')

これだけ記述が簡単になります。ModelSerializerには、

  • 自動でフィールドを設定してくれる
  • シンプルなcreate()update()メソッドがデフォルトで実装されている

ためです。

views.py

次はviews.pyを実装していきましょう。

snippets/views.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


@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
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)

snippet_list()はDBに登録されているSnippetモデルの全件取得と新規作成、snippet_detail()は個々のSnippetモデルの取得、更新、削除のためのメソッドです。記述量が多いですが、これらも後々もっとシンプルに書けるようになります。

urls.py

urls.pyを編集していきましょう。
まずsnippets/urls.pyを作成します。こちらのファイルも新規作成になります。

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

urlpatterns = [
    path('snippets/', views.snippet_list),
    path('snippets/<int:pk>/', views.snippet_detail),
]

大元のurls.pyに繋げましょう。

tutorial/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('snippets.urls')),
]

ここまでで一旦完成です。

テスト

テストをしていきましょう。
次のコマンドでローカルサーバーをたてます。

python manage.py runserver

別のターミナルを開いてローカルサーバーに適当なリクエストを送ってみましょう。次のリクエストはSnippetの全件取得のビューのエンドポイントに設定しましたね。

curl -X GET http://localhost:8000/snippets/
# []

空の括弧が返って来たと思います。何も登録してないので当然ですね。
適当なスニペットをPOSTで登録してみましょう。

curl -X POST -H 'Content-Type:application/json' -d '{"title":"hoge","code":"fuga"}' http://localhost:8000/snippets/
# [{"id": 1, "title": "hoge", "code": "fuga"}]

この状態で先ほどのGETコマンドを打つと、登録したスニペットが取得できると思います。
次は個別のスニペットにアクセスしてみましょう。

curl -X GET http://localhost:8000/snippets/1/
# {"id": 1, "title": "hoge", "code": "fuga"}

次はPUTcode部分を変えてみます。

curl -X PUT -H 'Content-Type:application/json' -d '{"code":"Hello"}' http://localhost:8000/snippets/1/
# {"id": 1, "title": "hoge", "code": "Hello"}

最後にこのスニペットを削除してみましょう。

curl -X DELETE http://localhost:8000/snippets/1/

削除後GETで再度取得しようとしても404エラーが返ってくるのが確認できればOKです。

チュートリアルの続きはこちらです。

Gattaca
いろいろと勉強中です。よろしくお願いします。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away