今日は、DRFのTutorial 2とTutorial 3に取り組みました。
内容を定着させるために、自分用に備忘録を書いておきます。
概要
結論から言うと、2と3に取り組んだことによって、views.pyのコードが劇的に短くなりました。
より簡潔で明快な実装が可能になったことで、手間いらずで、理解しやすく、再利用が容易であるというメリットがあります。
こういったコードは、DRYであると言うらしく、実用の場面では絶対に取り入れた方が良いでしょう。
しかし一方で、コードがブラックボックス化しやすく、私のような初学者にとっては何が起きているのか理解しにくいという側面があります。
なので、まずはそのコードの裏で何が起きているのかを理解することが、初学者にとっては必要なステップになります。そのために、チュートリアルに取り組んでいました。
Tutorial2と3で、それぞれおおまかにどのような事を学んだのかを、自分なりにアウトプットしたいと思います。
Tutorial 2
1. Responseオブジェクトの柔軟性
クライアントからのリクエストに対して、rest_framework.response.Responseクラスを使用することによって、レスポンスの種類を明示しないことで、より柔軟な対応をすることができるようになる。
例えば、JSONを出すリクエストに対しても、HTMLの場合でも、要求された通りの型のレスポンスを作ることができる。
2. request.data
クライアントから送られてくるrequestオブジェクトのdata属性に、リクエストの内容が入っているので、それを自分で定義したシリアライザのクラスに与えるだけで、指定したデータを取り出すことができる。
3. 明示的なステータスコード
rest_framework.statusモジュールを使うことで、HTTPレスポンスのステータスコードを整数のみで表現するよりも、人間が意味を理解しやすいコードを書くことができる。
(例:400→status.HTTP_400_BAD_REQUEST)
4. ビューのラッピング
-
@api_view:関数ベースのビューに使うデコレーター -
APIView:クラスベースのビューに継承させる基底クラス
これらは、CSRF対策を兼ねているが、それだけではなく、「Requestインスタンスの受け取りを保証する」「405 Method Not Allowed を適切に返す」「request.dataのパースエラーを処理する」といった機能も付加されている。
5. URLに追加の接尾語のフォーマットを追加
APIに与えるリクエストのパスの接尾語に、.../4.jsonといった接尾語を与えることで、APIがその要求に応えて適切なデータ型を返すことができるように、snippets/urls.pyにコードを追加。
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views
urlpatterns = [
path("snippets/", views.snippet_list),
path("snippets/<int:pk>/", views.snippet_detail),
]
urlpatterns = format_suffix_patterns(urlpatterns)
Tutorial 3
この章は、今まで関数ベースで書いていたビューを、クラスベースのものに変更した。
クラスベースにする事で得られる強力なメリットがある。それは、DRYなコードを書けるという事だ。
DRFにあらかじめ実装されている、ミックスインクラスを継承させることで、それが実現する。
結論から述べると、最終的なviews.pyの内容は、何と以下の内容のみで済んでしまう。
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import generics
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
snippet_list = SnippetList.as_view()
snippet_detail = SnippetDetail.as_view()
何をしているかというと、自分で定義したSnippetモデルと、JSONに変換するシリアライザに関して、「閲覧と作成」ができるレスポンスと、「再取得と編集、削除」ができるレスポンスを、クラスベースで定義している。
さらに、行末でas_view()関数を用いることによって、クラスを変数に変換している。これで、クラスベースのビューをurls.pyにパターンを渡すことができる。
このような、よく使われる「CRUD」オペレーションに対して、何度も同じようなコードを書く手間を省くために、ミックスインクラスを使う事ができる。
DRFのミックスインクラスを、クラスベースのビューに継承するだけで、よくあるCRUDオペレーションを簡単に実装することができる。
最終的なコードでは、「ミックスインジェネリックビュー」を使って、メソッドを書かなくてもCRUDオペレーションを実装できることを表している。
SnippetListではgenerics.ListCreateAPIViewを継承することで「閲覧と作成」、SnippetDetailクラスではgenerics.RetrieveUpdateDestroyAPIViewを継承することで「再取得と編集、削除」ができるようになっている。