Django REST framework 超入門
スポンサーリンク
今回は Django で rest な API を実装するのに超絶便利な Django REST framework を紹介します。
その名の通り、Django で RESTful な API を作るための framework になります。
APIの開発効率が何倍にも上がる代物ですので、ぜひみなさまにも使っていただきたいと思っています。
はじめに
前回作成した racchai
プロジェクトをベースに進めていきます。
まずは rest_framework のインストールから。
$ pip install djangorestframework $ pip install markdown $ pip install django-filter
次は racchai/settings.py
の INSTALLED_APPS に rest_framework
を追記します。
# Application definition INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'racchai', + 'rest_framework', )
これで準備は整いました!
簡単なAPIを作ってみる
その前に、前回の記事で作成したモデル情報を改めて用意します。
$ cat > racchai/models.py <<EOF from django.db import models class Writer(models.Model): name = models.CharField(max_length=128) class Article(models.Model): writer = models.ForeignKey(Writer, related_name='articles') title = models.CharField(max_length=512) contents = models.TextField() EOF
ここまでは Django を使う場合と一緒です。
Serializer を定義する
rest_framework では、Serializer と呼ばれるモジュールを利用するシーンが多いです。
等々、用途は様々です。
Serializer を制するものが rest_framework を制します。
今回は各モデルに対応する Serializer として、ModelSerializer
を継承したクラスを作成します。
$ cat > racchai/serializers.py <<EOF from rest_framework import serializers from racchai.models import Article, Writer class WriterSerializer(serializers.ModelSerializer): class Meta: model = Writer class ArticleSerializer(serializers.ModelSerializer): class Meta: model = Article EOF
今回は WriterSerializer と ArticleSerializer を作成しました。
Articleを全件取得する API を作ってみよう
次は API を作成します。
viewsets.ModelViewSet
を継承して、serializer_class
に対応する serializer を設定します。
apis.py
$ cat > racchai/apis.py <<EOF from rest_framework import viewsets, routers from racchai.models import Article from racchai.serializers import ArticleSerializer class ArticleViewSet(viewsets.ModelViewSet): queryset = Article.objects.all() serializer_class = ArticleSerializer router = routers.DefaultRouter() router.register(r'articles', ArticleViewSet) EOF
なんとこれだけで API が実装できています。
では、urls.py で実際のエンドポイントを定義しましょう。
$ cat > racchai/urls.py <<EOF from django.conf.urls import url, include from racchai import apis urlpatterns = [ url(r'^api/', include(apis.router.urls)), ] EOF
これで準備が整いました。一瞬でしたね。
それでは開発サーバーを起動して、Article一覧を取得してみます。
$ ./manage.py runserver $ curl http://localhost:8000/api/articles.json [{"id":1,"title":"title1","contents":"contents1","writer":1},{"id":2,"title":"title2","contents":"contents2","writer":1}]
無事Article情報が取得できました!
前回の記事では Django 組み込みの JSON シリアライザを利用しましたが、非常にクセの強い JSON が生成されてしまいました。
rest_framework を使えば納得(普通)の出力結果を得ることができます。
API 経由でArticleを作成してみよう
実は、viewsets.ModelViewSet
を継承した時点で、レコード取得・作成・更新・削除までできるようになっています。
API 経由でデータを登録するには、POST
を使います。
$ curl -X POST http://localhost:8888/api/articles.json -d "writer=1&title=hoge&contents=fuga" {"id":4,"title":"hoge","contents":"fuga","writer":1}
なんか登録されてるっぽいですね!
再度全件取得してみましょう。
$ curl http://localhost:8000/api/articles.json [{"id":1,"title":"title1","contents":"contents1","writer":1},{"id":2,"title":"title2","contents":"contents2","writer":1},{"id":3,"title":"hoge","contents":"fuga","writer":1}]
新たに登録されたレコードが取得できているのがわかりますね。
Serializer の機能いろいろ
特定のフィールドは出力したくない
ありますよね。ユーザーのパスワードフィールドとかは画面には表示しない、とか。
出力対象のフィールドは Serializer クラス内で制限することができます。
手段はいくつかありますが、今回は writer フィールドを書き込み専用フィールドとして上書きする方法で実現してみます。
class ArticleSerializer(serializers.ModelSerializer): + writer = serializers.IntegerField(write_only=True) class Meta: model = Article
上のようにArticleSerializerに一行足して、レコード情報を取得してみましょう。
$ curl http://localhost:8000/api/articles/3.json {"id":3,"title":"hoge","contents":"fuga"}
無事、writer が表示されなくなりました。
外部キー参照先はキー値じゃなくてオブジェクトとして取得したい
今回でいう、writer はオブジェクトで取得したい!ということですが、これも簡単に実現が可能です。
class ArticleSerializer(serializers.ModelSerializer): + writer = WriterSerializer() class Meta: model = Article
writer フィールドを WriterSerializer
で上書きしてしまうだけです。
それでは確認してみます。
$ curl http://localhost:8000/api/articles/3.json {"id":3,"writer":{"id":1,"name":"racchai"},"title":"hoge","contents":"fuga"}
無事参照先レコードもオブジェクトとして取得できてますね。
外部キー参照先も同時に作成したい
参照がオブジェクトで取得できるなら、作成も同様にオブジェクト形式で送信したいですよね。
もちろん可能です。
ArticleSerializer
を以下のように編集しましょう。
class ArticleSerializer(serializers.ModelSerializer): writer = WriterSerializer() class Meta: model = Article + def create(self, validated_data): + writer = Writer(**validated_data.pop('writer')) + writer.save() + return super(ArticleSerializer, self).create(dict(validated_data, **{'writer': writer}))
やってることとしては、デフォルトの create 動作前に Writer を作成してるだけです。
では登録してみましょう。
今回はリクエストデータ自体も JSON にしてみます。
$ curl http://localhost:8000/api/articles.json -X POST -d "{\"writer\":{\"name\":\"new writer\"},\"title\":\"aaa\",\"contents\":\"bbb\"}" -H "Content-Type: application/json" │ {"id":4,"writer":{"id":2,"name":"new writer"},"title":"aaa","contents":"bbb"}
登録できてそうですね!
念のため登録したArticleを取得してみます。
$ curl http://localhost:8888/api/articles/4.json {"id":4,"writer":{"id":2,"name":"new writer"},"title":"aaa","contents":"bbb"}
作成時のレスポンスと同様のデータが取得できました。
まとめ
以上、簡単に Django REST framework について紹介してみました。
細かく解説できていない点も多いですが、簡単に API を実装できるイメージは伝わったかと思います。
本記事ではほんのさわりだけ紹介しましたが、まだまだいろんな機能が隠されています。
これからも、本ブログでは Django REST framework のノウハウについて紹介していきますので、お楽しみに!