Django REST framework

django使い始めました。

最近pythonの勉強がてらdjangoというWebアプリを作るフレームワークを使い始めました。昔Ruby on Railsを使ったのですがあの言語の仕様を駆使した使い方は最終的に何やっているか訳が分からなくなり挫折しました。

django入門を突破したあと

djangoはそれに比べると素晴らしく簡単にできました。簡単なんで色々作りたくなったのですがRailsに比べると入門以外の資料が少なく最初のチュートリアルを超えたことをしようとするとつまずきました。

Django REST frameworkが良さそう

ただモジュール配布元のオリジナル英語サイトはよくできていていることに気がつきました。つまづいた箇所はデータベースから検索するアプリです。Django REST frameworkというモジュールを使えば出来るかもと思い調べ始めました。書きましたように結局オリジナルサイトが一番良さそうでした。

訳してみる。

そこで使えるようになるために訳してみることにします。あとは自分のメモの意味もあります。

www.django-rest-framework.org


f:id:mechagocha:20201208165033p:plain

クイックスタート

管理者使うことができる簡単なAPIを作り、ユーザーとグループが編集出来るようにします。

プロジェクトセットアップ

tutorialという名前のDjangoプロジェクトを作って、quickstartという名前の新しいアプリをスタートさせます。

# Create the project directory
mkdir tutorial
cd tutorial

# Create a virtual environment to isolate our package dependencies locally
python3 -m venv env
source env/bin/activate  # On Windows use `env\Scripts\activate`

# Install Django and Django REST framework into the virtual environment
pip install django
pip install djangorestframework

# Set up a new project with a single application
django-admin startproject tutorial .  # Note the trailing '.' character
cd tutorial
django-admin startapp quickstart
cd ..

プルジェクトの構成は次のようになります。

$ pwd
<some path>/tutorial
$ find .
.
./manage.py
./tutorial
./tutorial/__init__.py
./tutorial/quickstart
./tutorial/quickstart/__init__.py
./tutorial/quickstart/admin.py
./tutorial/quickstart/apps.py
./tutorial/quickstart/migrations
./tutorial/quickstart/migrations/__init__.py
./tutorial/quickstart/models.py
./tutorial/quickstart/tests.py
./tutorial/quickstart/views.py
./tutorial/settings.py
./tutorial/urls.py
./tutorial/wsgi.py

プロジェクトディレクトリー内のアプリケーションが作られた場所はいつもとはちょっと違うかもしれません。プロジェクトのネームスペースを使っているのは名前が外部モジュールと衝突を防ぐためです。(クイックスタートのスコープの外へ行くトピックなどのように。)

python manage.py migrate

次にパスワードをpassword123にしたadmin初期ユーザーとして作成します。後でこのユーザーがこの例では認証されたユーザになります。

python manage.py createsuperuser --email admin@example.com --username admin

一度データベースをセットアップして、この初期ユーザーを作って準備を終わらせます。アプリのディレクトリを開いてコーディングを続けましょう。

シリアライズ

まずいくつかのシリアライザーを定義します。この例で使うデータを現したtutorial/quickstart/serializers.pyという名前の新しいモジュールを作りましょう。

from django.contrib.auth.models import User, Group
from rest_framework import serializers


class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ['url', 'username', 'email', 'groups']


class GroupSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Group
        fields = ['url', 'name']

このケースではハイパーリンクで関連づけられた HyperlinkedModelSerializerを使っています。またプライマリーキーや他の関連づけられたものも使えます。ただしハイパーリンクにすることはRESTfulのデザインでは良いことです。

ビュー

そうですね我々はいくつかのビューを描いてみたいですね。tutorial/quickstart/views.py を開いてくだい。そして次のようにタイプして下さい。

from django.contrib.auth.models import User, Group
from rest_framework import viewsets
from rest_framework import permissions
from tutorial.quickstart.serializers import UserSerializer, GroupSerializer


class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer
    permission_classes = [permissions.IsAuthenticated]


class GroupViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows groups to be viewed or edited.
    """
    queryset = Group.objects.all()
    serializer_class = GroupSerializer
    permission_classes = [permissions.IsAuthenticated]

いろんなビューを書くよりは同じ振る舞いをする全てをViewSetsと呼ばれるクラスへまとめる方が良いです。 もし必要であれば簡単に独立したビューにすることができます。しかしviewsetsを使えば統一された綺麗なビューロジックを保ちまたとても簡潔にできます。

URLs

さてこれからAPI URLsをつないでいきましょう。tutorial/urls.pyの中を。。。

from django.urls import include, path
from rest_framework import routers
from tutorial.quickstart import views

router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)

# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
    path('', include(router.urls)),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

viewsの代わりにviewsetsを使っている理由は、viewsetsでルータークラスを単純な登録することで、APIでURLを自動的に生成できます。 もう一度書きますともしもっとコントロールが必要なAPI URLがあれば簡単に通常のクラスベースのviewsに置き換えられ、明確にURLの設定が書けます。 最後にこのモジュールはブラウズ可能なデフォルトのログイン、ログアウトビュー使うために組み込まれています。これはオプションですが、APIの認証が必要とされ貴方がブラウズ可能なAPIを使いたいのであれば役に立ちます。

ページネーション

ページネーションは1ページあたりどのくらいオブジェクトを返すかコントロールするものです。これを有効にするには次の内容をtutorial/settings.pyに追加します。

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10
}

セッティング

'rest_framework'をINSTALLED_APPSを追加して下さい。このセッティングモジュールはtutorial/settings.pyにあります。

INSTALLED_APPS = [
    ...
    'rest_framework',
]

できましたね。


APIテスト

今我々の作ったAPIのテスト準備ができています。さぁコマンドラインからサーバーをガツンと動かしてみましょう。

python manage.py runserver

今まさに作ったAPIコマンドラインからcurlのようなツールでアクセスできます。

bash: curl -H 'Accept: application/json; indent=4' -u admin:password123 http://127.0.0.1:8000/users/
{
    "count": 2,
    "next": null,
    "previous": null,
    "results": [
        {
            "email": "admin@example.com",
            "groups": [],
            "url": "http://127.0.0.1:8000/users/1/",
            "username": "admin"
        },
        {
            "email": "tom@example.com",
            "groups": [],
            "url": "http://127.0.0.1:8000/users/2/",
            "username": "tom"
        }
    ]
}

もしくはコマンドラインツールのhttpieをつかてみると

bash: http -a admin:password123 http://127.0.0.1:8000/users/

HTTP/1.1 200 OK
...
{
    "count": 2,
    "next": null,
    "previous": null,
    "results": [
        {
            "email": "admin@example.com",
            "groups": [],
            "url": "http://localhost:8000/users/1/",
            "username": "paul"
        },
        {
            "email": "tom@example.com",
            "groups": [],
            "url": "http://127.0.0.1:8000/users/2/",
            "username": "tom"
        }
    ]
}

もしくは直接ブラウザを通してURL http://127.0.0.1:8000/users/ をアクセスできます。

https://www.django-rest-framework.org/img/quickstart.png

うまくブラウザが動作したら、右上の角のコントロールを使ってログインを確認して下さい。 バッチリですね。簡単でしたね。 もしRESTフレームワークがどのようにそれぞれ協力して動いているかについての深い理解を望んでいるならば チュートリアルもしくはAPIガイドを見てください。