Django REST framework (DRF)入門 概念、考え方、全体像のImage付き

Django REST framework (DRF)入門 概念、考え方、全体像のImage付き

DRFを使い始める時って「serializerってなんだ」とか「controllerがない?」とかrailsとか他のMVCフレームワークをやってた人からするとわかりにくい部分があると思います。

また、APIを初めて作成する人はそもそもフレームワークで何をできるのかもわからないと思います。

なのでこの記事では具体的に開発に入る前にDRFの概念的な部分を説明できればと思います。

REST APIとは

ここでは簡単な紹介ですが、そもそもですが、REST APIというのは個人的には以下の二つの考えでできたものだと考えています。

  • DBのテーブル一つ一つにCRUD(Create,Read,Update,Delete)処理を行うリクエストを用意すればシンプルじゃね?
  • URIの命名よりもHTTPのメソッドを使った方が処理の内容がわかりやすいんじゃね?

例えばblogなどサイトを運用するとして、記事についての操作をするには「記事の作成」、「閲覧」、「一覧の閲覧」、「編集」、「削除」を行うリクエストを以下のように準備します。

URLHTTP method意味
api.sample.com/v1/article/POST新規作成
api.sample.com/v1/article/GET一覧参照
api.sample.com/v1/article/1/GET詳細表示
api.sample.com/v1/article/1/UPDATE新規作成or更新
api.sample.com/v1/article/1/PATCH更新
api.sample.com/v1/article/1/DELETE削除

そしてそれらのリクエストに対して処理を行い、レスポンスを返します。レスポンスは基本的にはjson,もしくはxmの形式で返します。

REST APIのFrameworkにはどんな機能があったら便利?

DRFの説明をしていってもいいのですが、何か勉強するときには自分で予測しながら勉強すると学びやすいと思います。

なのでまずは自分でREST API を作りやすくしてくれるFrameworkにはどんな機能があったら便利か考えてみましょう。

……
…….

私はDRFを触ってるのでバイアスも入ってしまいますが、個人的には以下のように考えました。
「まずは、REST APIはテーブルひとつひとつにリクエストを作っていく、リソース指向な考え方だから、テーブルの定義を記述するところさえあれば、それを書くと自動でCRUDのリクエストを作成してくれたら楽では?
…いやでもそうするとまだまだ問題があるから以下の機能も必要だなあ」

  • テーブル名をURLにしたくない場合もあるからURLの名前を決める、ルーティングを記述する機能も必要。
  • 会員制のサイトなどでは誰でもAPIを触ってはいけない場合もあるから、各APIについてpermissionを記述する機能も必要。
  • GETのリクエストに対して全件を見せると重くなるからpagingも必要だし、検索向けにfiltering機能も必要。
  • UserのテーブルについてのGETの時とかはpasswordとか見せたくない情報もあるからそれを制限する機能も必要。

まあ話の流れからわかると思いますが、djangoではこれら+便利機能を実装してくれていますので次で説明します。

Django REST frameworkとは

まず公式サイトを見てみても「英語。。」心が折れる方は多いと思いますので補足しますと、

そもそもDRFはDjangoというweb frameworkに追加して使うtoolkitで、REST API を開発しやすくしてくれています。なので基本的にはDjangoを勉強してからDRFの勉強をするとわかりやすいです。

ここからは、具体的にDRFの機能、それに対応するファイルを以下で説明します。

models.py

DBのTable定義を記載する部分になります。Djangoではmodel.pyにTableの記載をして、それをDBにMigrateします。そして実際にSQLなどを使わなくてもarticle.objects.all()などと書くと全件取得できたりします。ORMの部分です。

urls.py

ルーティングの設定を行います。URLの命名をどのようにするのかをこちらに記載します。例えば、以下のコードは/articlesというリクエストが来たらArticleViewSetというメソッドで処理をするという意味です。

router.register(r'articles', ArticleViewSet,base_name='articles')

views.py

上記のurl.pyによってルーティングがされ、実際に処理を記述する部分になります。permissionやpaging,filteringもこちらに記載します。基本的にはserializerを設定し、対象となるmodel(厳密にはquery)を設定するとResponseを返してくれます。ただし、ビジネスロジックを書きたい場合や、画面の取得用のAPIの場合には複数のmodelを返す必要があるのでその場合にはviews.pyにゴリゴリ書いたりします。( REST APIではPerformanceのため、tableごとのURL以外にも画面表示用は作ることを推奨されてます。 )

serializer.py

models.pyによって定義されたObjectとJsonを相互に変換するものになります。JavaではtoString()メソッドがありますが、そちらに少し似ています。ただしserializerはObject ->Json に変換もできますし、POSTなどで受け取ったRequest Body をObjectに変換することもできます。
「変換するだけなら、Serializerの記載をなくし、裏で自動で変換すればいいじゃないか」と思われるかもしれません。
しかし、例えば、GET /user/1 のpasswordは見せたくないなどの設定をしたい場合もあると思いますし、外部キーでつながってるこのカラムも含ませたい。などあると思います。それをアレンジできるのがSerializerのいいところです。
MVCではmodel やcontroller がでっかくなりがちだと思いますが、DRFではRESTがシンプルというのもあるし、serializerがあることで割とバランスよく記述できると思います。

DRFの全体像

DRF 全体像のイメージ

言葉だけではわからないと思うので、DRFの全体像のイメージを図にしてみました。

ここまででDRFの概念や考え方についての説明は終了になります。

慣れれてくれば、4時間くらいで新しいtableを作ってCRUDのAPIを4つほど作って、TESTもカバレッジ100%にすることができると思います。(TESTの書き方は別途紹介します。)pythonが好きで、REST APIを作りたい方にはDRFはおすすめです。

長い記事を読んでいただきありがとうございます。皆様の理解の助けになれば幸いです。また、説明が間違っている部分もあると思います。その際はご指摘いただけると幸いです。

DRFの開発の仕方や、他のrest api framework (Node.jsのExpressかな?)との比較などについても時間ができたら書いていきたいと思います。