Django REST FrameworkでAPIを実装


未来電子テクノロジーでインターンをしている箕牧和廣です。
今回はDjango REST Frameworkについて書いていこうと思います。

プログラミング初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正するのでどんどん指摘してください。

Django REST Frameworkとは

DjangoでWebAPIを開発することをサポートしてくれるライブラリ。RESTfulなAPIの開発をライブラリの標準としてサポートしている。

早速インストール

必要なライブラリをインストール
terminal
$ pip install django
$ pip install djangorestframework
$ pip install django-filter 
プロジェクト・アプリの作成
terminal
# django_rest_framework_testという名前でプロジェクトを作ってみます
$ django-admin startproject django_rest_framework_test
$ cd django_rest_framework_test/

$ python manage.py startapp blog

# ディレクトリ構造確認
.
└── django_rest_framework_test
    ├── blog
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── migrations
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    ├── django_rest_framework_test
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    └── manage.py
モデルの定義
blog/models.py
from django.db import models


class User(models.Model):
    name = models.CharField(max_length=32)
    mail = models.EmailField()


class Entry(models.Model):
    STATUS_DRAFT = "draft"
    STATUS_PUBLIC = "public"
    STATUS_SET = (
            (STATUS_DRAFT, "下書き"),
            (STATUS_PUBLIC, "公開中"),
    )
    title = models.CharField(max_length=128)
    body = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    status = models.CharField(choices=STATUS_SET, default=STATUS_DRAFT, max_length=8)
    author = models.ForeignKey(User, related_name='entries', on_delete=models.CASCADE)

名前とメールアドレスだけを持ったUserと、ブログの記事を表すEntryを定義。Entryからブログの書いた人の情報としてForeignKeyでUserを参照。

データベース構築

django_rest_framework_test/settings.py
# blogを追記
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
]
terminal
# migrationファイルを作る
$ python manage.py makemigrations
# migrationファイルを元にDBに反映する
$ python manage.py migrate

自分で定義したモデルを追加。

blog/admin.py
from django.contrib import admin

from .models import User, Entry


@admin.register(User)
class UserAdmin(admin.ModelAdmin):
    pass

@admin.register(Entry)
class Entry(admin.ModelAdmin):
    pass
動作確認
terminal
# admin用のユーザー作成
$ python manage.py createsuperuser
    Username (leave blank to use 'kimihiro_n'): dev
    Email address:
    Password:
    Password (again):

# 開発サーバーを起動
$ python manage.py runserver

http://localhost:8000/adminでDjangoの管理画面に入れる。
ここまでで通常のDjangoの流れは終了。

Djagno REST Frameworkを組み込む

REST Frameworkの読み込み
django_rest_framework_test/settings.py
INSTALLED_APPS = (
    ...
    'blog',
    'rest_framework',
)
Serializerの定義
blog/serializer.py
# coding: utf-8

from rest_framework import serializers

from .models import User, Entry


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('name', 'mail')


class EntrySerializer(serializers.ModelSerializer):
    class Meta:
        model = Entry
        fields = ('title', 'body', 'created_at', 'status', 'author')

serializers.ModelSerializerを継承してModelに対応するSerializerを作成。 fieldsに与えるのはAPIとして出力したいフィールド名のタプル。filedsに列挙したものはデフォルトの実装でシリアライズして出力される。

ViewSetの定義
blog/views.py
# coding: utf-8

import django_filters
from rest_framework import viewsets, filters

from .models import User, Entry
from .serializer import UserSerializer, EntrySerializer


class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer


class EntryViewSet(viewsets.ModelViewSet):
    queryset = Entry.objects.all()
    serializer_class = EntrySerializer

querysetにDjangoのModelのクエリセットを、serializer_classに先ほど定義したSerializerを指定。querysetはあらかじめフィルタリングすることも可能。

URL pattern定義
django_rest_framework_test/urls.py
# coding: utf-8

from django.conf.urls import url, include
from django.contrib import admin

from blog.urls import router as blog_router

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # blog.urlsをincludeする
    url(r'^api/', include(blog_router.urls)),
]
blog/urls.py
# coding: utf-8

from rest_framework import routers
from .views import UserViewSet, EntryViewSet


router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
router.register(r'entries', EntryViewSet)

最後にURL patternの定義。routerというものを使ってModel毎に登録。
上記のように設定した場合、/api/がREST APIへの入り口となっており、GET /api/users/ でUserの一覧、GET /api/entries/でEntryの一覧へとアクセス出来る。

API動作確認

これでREST APIが動かせる状態になった。

terminal
python manage.py runserver

でサーバーを起動させ、http://localhost:8000/api/にアクセス。