django使い始めました。
最近pythonの勉強がてらdjangoというWebアプリを作るフレームワークを使い始めました。昔Ruby on Railsを使ったのですがあの言語の仕様を駆使した使い方は最終的に何やっているか訳が分からなくなり挫折しました。
django入門を突破したあと
djangoはそれに比べると素晴らしく簡単にできました。簡単なんで色々作りたくなったのですがRailsに比べると入門以外の資料が少なく最初のチュートリアルを超えたことをしようとするとつまずきました。
Django REST frameworkが良さそう
ただモジュール配布元のオリジナル英語サイトはよくできていていることに気がつきました。つまづいた箇所はデータベースから検索するアプリです。Django REST frameworkというモジュールを使えば出来るかもと思い調べ始めました。書きましたように結局オリジナルサイトが一番良さそうでした。
訳してみる。
そこで使えるようになるために訳してみることにします。あとは自分のメモの意味もあります。
クイックスタート
管理者使うことができる簡単な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/ をアクセスできます。
うまくブラウザが動作したら、右上の角のコントロールを使ってログインを確認して下さい。 バッチリですね。簡単でしたね。 もしRESTフレームワークがどのようにそれぞれ協力して動いているかについての深い理解を望んでいるならば チュートリアルもしくはAPIガイドを見てください。