Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Django REST Framework はじめの一歩 〜 押さえておきたい3つのポイント 〜 / First step of Django REST Framework (stapy#87 2022)

akiyoko
November 10, 2022

Django REST Framework はじめの一歩 〜 押さえておきたい3つのポイント 〜 / First step of Django REST Framework (stapy#87 2022)

Django で RESTful な API バックエンドを構築するとなれば「Django REST Framework(DRF)」パッケージを使うのがほぼデファクトになっています。このトークでは、Django は少し知っているけど DRF は未経験という方をターゲットに、これだけは押さえておきたい3つのポイントについて解説します。

2022.11.10 みんなのPython勉強会#87
https://startpython.connpass.com/event/263565/

akiyoko

November 10, 2022
Tweet

More Decks by akiyoko

Other Decks in Programming

Transcript

  1. Django REST Framework
    はじめの⼀歩
    〜 押さえておきたい3つのポイント 〜
    2022.11.10 みんなのPython勉強会#87
    横瀬 明仁(akiyoko)

    View Slide

  2. ⽬次
    1. はじめに
    2. DRF とは?
    3. ポイント①:全体像を把握しよう
    4. ポイント②:シリアライザはフォームっぽく使える
    5. ポイント③:起点は DRF ⽤ビュー
    6. まとめ
    1
    ( 2 min )
    ( 5 min )
    ( 5 min )
    ( 5 min )
    ( 7 min )
    ( 1 min )
    ※ 本トークのコードは Django 3.2 LTS / DRF 3.14 で動作確認

    View Slide

  3. ⾃⼰紹介
    ⾃費出版本 :
    2
    『現場で使える Django の教科書《基礎編》』
    『現場で使える Django の教科書《実践編》』
    『現場で使える Django REST Framework の教科書』
    『現場で使える Django 管理サイトのつくり⽅』
    名前 : 横瀬 明仁(akiyoko)
    名前 : Python / Django 推しのバックエンドエンジニア
    Twitter : @aki_yok
    ブログ : akiyoko blog(https://akiyoko.hatenablog.jp/)
    Django 歴 : 9年くらい

    View Slide

  4. トークの⽬的
    3
    Django REST Framework(DRF)がどんなものかを
    ざっくり理解しよう
    %3'φχϞϫΧϥφΠ %3'׬શʹཧղͨ͠

    View Slide

  5. 皆さん
    DRF、使ってますか?
    4

    View Slide

  6. Django 開発者の「73%」が DRF を使っている
    5
    akiyoko 独⾃アンケート
    (2022年10⽉実施)
    Q.DRF(Django REST Framework)を使っていますか?(N=97)

    View Slide

  7. お気に⼊り Django パッケージランキングで DRF が1位!
    6
    Q.What are your 5 favorite third-party Django packages? (N>7000)
    https://lp.jetbrains.com/django-developer-survey-2021-486/
    Django Developers Survey 2021
    7000名を超えるアンケートで
    「djangorestframework」が
    ナンバーワン Django パッケージに
    選出される

    View Slide

  8. DRF って何?
    7

    View Slide

  9. DRF とは?
    8
    DRF(Django REST Framework)は
    REST API を作成する際の多彩なニーズに応えるための
    超ド定番 Django パッケージ
    • Django 単体では不⾜している機能を DRF で補完
    • Django 開発者が理解しやすい作り
    特徴

    View Slide

  10. • スマホや SPA のバックエンドとして REST API がよく利⽤される
    • フロントエンド/バックエンド開発者が理解しやすいシンプルな設計
    • 共通の枠組みを介してフロントエンドとバックエンドを疎結合化
    • リソース中⼼の設計で、モデル中⼼の Django と親和性が⾼い
    REST API の利⽤イメージ
    9
    スマホアプリ
    / SPA
    /books/1/
    ボディ {
    "price": 2000
    }
    PUT
    HTTPメソッド
    U R L
    REST API
    ボディ
    201(Created)
    ステータス
    {
    "id": 1,
    "title": "DRFの本",
    "price": 2000
    }
    HTTPメソッドでリソースへの操作を表す
    https://example.com/api/v1/books/1/
    URI でリソースを特定
    PUT
    【 REST API の例 】
    JSON
    リクエスト
    JSON
    レスポンス
    DRF
    アプリケー
    ション

    View Slide

  11. DRF が得意なこと
    10
    単⼀リソースの CRUD を処理する REST API なら超簡単!!
    表1.REST API の例
    ⇒ 最短 20⾏くらいで書ける!(モデル除く)

    View Slide

  12. 【よくある誤解①】DRF では単⼀リソースを扱う API 以外は作れない
    11
    • リソースがネストした API
    • 独⾃アクションを追加した API
    • リソースに紐付いていない API
    作れる!
    表2.リソースがネストした API の例 表3.独⾃アクションを追加した API の例
    表4.リソースに紐付いていない API の例
    (が、詳細については本トークの範囲外)

    View Slide

  13. 【よくある誤解②】DRF なしでは JSON のやり取りができない
    12
    import json
    from django.forms.models import model_to_dict
    from django.http.response import JsonResponse
    from django.views.generic import View
    from shop.models import Book
    class BookListCreateView(View):
    """本モデルの登録APIクラス"""
    def post(self, request, *args, **kwargs):
    """本モデルの登録API⽤のメソッド"""
    data = json.loads(request.body)
    # バリデーションを実⾏
    if not data.get('title'):
    return JsonResponse({'message': 'タイトルは必須です。'}, status=400)
    # モデルオブジェクトを登録
    book = Book(**data)
    book.save()
    # レスポンスオブジェクトを作成して返す
    return JsonResponse(model_to_dict(book), status=201)
    ⇒ 共通化したいというニーズから DRF が誕⽣した
    (できれば Django っぽい書き⽅で) (んだと思う)
    Ͱ͖ͳ͘ͳ͍͚Ͳɺ
    ਖ਼௚͠ΜͲ͍ͳ ʜ
    api/views.py
    ⼊⼒データとなる JSON⽂字列
    (request.body)をパースして
    バリデーションを実⾏し、モデ
    ルオブジェクトにデータを詰め
    替えて永続化して、最後に
    JsonResponse を返す

    View Slide

  14. メリット
    13
    • Django のノウハウやエコシステムが活⽤できる
    • ⼈気があり、枯れている
    • 公式ドキュメントやチュートリアルが充実(英語のみ)
    • 機能が充実している
    • Cookie認証・トークン認証・JWT認証 (*) など API でよく利⽤される認証
    • パーミッション(アクセス権制御)
    • フィルタリング(クエリ⽂字列による検索)
    • ページネーション(ページ表⽰に対応した JSON レスポンス)
    • スロットリング(利⽤回数制限)
    • 画⾯で API を実⾏確認できるテストクライアント(Browsable API)
    • OpenAPI に準拠した API ドキュメントを出⼒
    (*) DRF 外のパッケージが必要
    %3'͕͋Ε͹
    ԿͰ΋Ͱ͖Δʂ

    View Slide

  15. デメリット
    14
    レスポンス
    の返却
    View
    View
    View
    View
    モデル
    データベース
    ビューの
    呼び出し
    データベース操作
    クエリ
    発⾏
    バリデーション・
    フォームの組み⽴て
    URLconf
    通常の
    Django ⽤
    ビュー
    View
    View
    フォーム
    URLパターン
    の登録
    ビューの
    呼び出し
    View
    View
    View
    View
    テンプレー

    View
    View
    シリアライ

    バリデーション・
    JSONの組み⽴て
    HTMLコードの組み⽴て
    DRF ⽤
    ビュー




    %


    (

    *




    /

    DRFプロジェクト の全体像
    ෳࡶ リクエスト
    レスポンス
    %KBOHP͚ͩͰ΋
    ෳࡶͳͷʹʜ

    View Slide

  16. そこで・・
    15

    View Slide

  17. 押さえておきたい3つのポイント
    16
    ポイント①:全体像を把握しよう
    ポイント②:シリアライザはフォームっぽく使える
    ポイント③:起点は DRF ⽤ビュー

    View Slide

  18. 17
    ポイント①:全体像を把握しよう
    ポイント②:シリアライザはフォームっぽく使える
    ポイント③:起点は DRF ⽤ビュー

    View Slide

  19. 全体像と登場⼈物(通常の Django プロジェクト)
    18
    View
    View
    View
    View
    モデル
    ビューの
    呼び出し
    データベース操作
    バリデーション・
    フォームの組み⽴て
    URLconf
    通常の
    Django ⽤
    ビュー
    View
    View
    フォーム
    URLパターン
    の登録
    View
    View
    テンプレー

    HTMLコードの組み⽴て




    %


    (

    *




    /

    Django プロジェクトの全体像
    コンポーネント 概要
    URLディスパッ
    チャ
    URLconf にしたがってリクエストURLに応じたビュー
    関数を呼び出す。ビュー関数からのレスポンスや例外の
    ハンドリングもおこなう
    URLconf URLパターンとビュー関数のマッチング情報などを保持
    したモジュール
    ミドルウェア リクエストの前処理とレスポンスの後処理をおこなう
    ビュー モデルやフォーム、テンプレートと連携してレスポンス
    を作成する
    フォーム ⼊⼒フォームのデータをオブジェクトとして扱うための
    ⼊れ物。⼊⼒データのバリデーションもおこなう
    モデル モデルクラスとテーブルの定義を紐付ける ORM として
    の機能を提供
    テンプレート 特別な記法で動的に変更する内容を記述できるHTML
    ファイル
    レスポンス
    の返却
    表5.Django プロジェクトの登場⼈物

    View Slide

  20. 全体像と登場⼈物(DRF プロジェクト)
    19
    レスポンス
    の返却
    View
    View
    View
    View
    モデル
    ビューの
    呼び出し
    データベース操作
    バリデーション・
    フォームの組み⽴て
    URLconf
    通常の
    Django ⽤
    ビュー
    View
    View
    フォーム
    URLパターン
    の登録
    ビューの
    呼び出し
    View
    View
    View
    View
    テンプレー

    View
    View
    シリアライ

    バリデーション・
    JSONの組み⽴て
    HTMLコードの組み⽴て
    DRF ⽤
    ビュー




    %


    (

    *




    /

    リクエスト
    レスポンス
    DRF プロジェクトの全体像
    起点
    コンポーネント 概要
    URLディスパッ
    チャ
    Django と同じ
    URLconf Django と同じ
    ミドルウェア Django と同じ
    ビュー DRF の起点となる DRF⽤のビュー。モデルやシリアラ
    イザと連携してレスポンスを作成する
    フォーム 使わない(共存も可能)
    モデル Django と同じ
    テンプレート 使わない(共存も可能)
    シリアライザ ⼊出⼒となる JSON データをオブジェクトとして扱うた
    めのクラス。⼊⼒データのバリデーションもおこなう。
    使い⽅はフォームと類似
    表6.DRF プロジェクトの登場⼈物

    View Slide

  21. ポイント① まとめ:全体像を把握しよう
    20
    DRF では
    • DRF⽤のビュー を作成して URLconf に登録
    • シリアライザ を使う
    • ⼊出⼒の JSON(およびモデルとの連携)定義とバリデーションを担当
    • フォームとテンプレートは使わない
    それ以外は通常の Django とだいたい同じ

    View Slide

  22. 21
    ポイント①:全体像を把握しよう
    ポイント②:シリアライザはフォームっぽく使える
    ポイント③:起点は DRF ⽤ビュー

    View Slide

  23. シリアライザの使いどころ
    22
    シリアライザは
    • ⼊⼒データのバリデーション
    • (モデルオブジェクトの永続化)
    • 出⼒データの作成
    を担当
    バリデーションOKの場合
    ビュー
    JSON レスポンス
    (正常)
    バリデーションNGの場合
    JSON レスポンス
    (400 エラー)
    URLディスパッチャ
    モデルオブジェクトを登録・更新・削除
    シリアライザオブジェクトからレスポンスオブジェクトを作成
    シリアライザオブジェクトを作成
    登録
    API
    更新・⼀部更新
    API
    削除
    API
    取得(詳細)
    API
    バリデーションを実⾏
    取得(⼀覧)
    API
    pk pk pk クエリ⽂字列
    JSON レスポンス
    (404 エラー)
    リソースが⾒つからない場合
    (pk やクエリ⽂字列を使って)モデルオブジェクトを取得
    シリアライザオブジェクトを作成
    S M
    シリアライザ モデル
    = =
    S S
    M
    S
    S
    S M
    /

    View Slide

  24. シリアライザはフォームっぽく使える
    23
    モデルと紐付いた REST API の場合は
    rest_framework.serializers.ModelSerializer
    を使うのが簡単
    • 使い⽅は ModelForm とほぼ同じ
    • バリデーションメソッドは「is_valid」、
    永続化メソッドは「save」
    • バリデーション済みのデータは
    「validated_data」にアクセス (フォームと
    変数名が異なるので注意)
    ModelForm
    cleaned_data
    値をセット
    errors
    属性
    属性
    ModelSerializer
    validated_data
    値をセット
    errors
    属性
    属性
    シリアライザ
    ⼊⼒データ
    モデル
    オブジェクト
    ⼊⼒データ
    モデル
    オブジェクト
    フォーム
    (更新時)
    (更新時)
    data
    引数
    data
    引数
    instance
    引数
    instance
    引数



    $

    &




    $

    &

    永続化
    永続化

    View Slide

  25. シリアライザの利⽤イメージ
    24
    from rest_framework import serializers
    from shop.models import Book
    class BookSerializer(serializers.ModelSerializer):
    """本モデル⽤シリアライザ"""
    class Meta:
    model = Book
    fields = ['id', 'title', 'price']
    # fields = '__all__'
    # exclude = ['created_at']
    api/serializers.py
    >>> from api.serializers import BookSerializer
    >>> serializer = BookSerializer(data={'title': 'DRFの本', 'price': 1000})
    >>> serializer.is_valid()
    True
    >>> serializer.validated_data
    OrderedDict([('title', 'DRFの本'), ('price', 1000)])
    >>> book = serializer.save()
    >>> serializer = BookSerializer(instance=book, data={'price': 2000}, partial=True)
    >>> serializer.is_valid()
    True
    >>> serializer.save()

    利⽤⽅法
    ModelSerializer
    validated_data
    値をセット
    errors
    属性
    属性
    ⼊⼒データ
    モデル
    オブジェクト
    (更新時)
    data
    引数
    instance
    引数



    $

    &

    永続化
    登録時は引数 data
    に⼊⼒データを渡す
    更新時は引数 instance にモデル
    オブジェクト、引数 data に⼊⼒
    データを渡す
    (partial=True は⼀部更新)

    View Slide

  26. ポイント② まとめ:シリアライザはフォームっぽく使える
    25
    • モデルと紐付いた REST API の場合は ModelSerializer を
    使うのが簡単
    • 使い⽅は ModelForm とほぼ同じ

    View Slide

  27. 26
    ポイント①:全体像を把握しよう
    ポイント②:シリアライザはフォームっぽく使える
    ポイント③:起点は DRF ⽤ビュー

    View Slide

  28. APIView とは?
    27
    • APIView を継承することで、さまざまな前処理
    と後処理をやってくれる
    • 2. 〜 6. は差し替え可能(プラガブル)
    • 設定ファイルの「REST_FRAMEWORK」で全体設
    定、クラス変数をオーバーライドしてビュークラス
    単位での個別設定が可能
    APIView を継承したビュー
    APIView による
    前処理
    ビューの処理
    APIView による
    後処理
    7. 例外ハンドリング
    1. リクエストオブジェクトを DRF ⽤に変換
    2. レンダラクラスとメディアタイプを決定
    3. バージョニング
    4. 認証チェック
    5. パーミッションチェック
    6. スロットリング
    rest_framework.views.APIView は
    DRF の起点となる基底ビュークラス

    View Slide

  29. DRF ⽤のビューは3種類
    28
    DRF ⽤ビューは、⽤途に応じて
    1)〜 3)のいずれかを継承して作成
    1)rest_framework.views.APIView
    2)rest_framework.generics.CreateAPIView などの 汎⽤ APIView
    3) rest_framework.viewsets.ModelViewSet 系ビュー
    カスタム性
    コード量


    Django
    DRF
    django.views.generic.base
    View
    (汎⽤ APIView) ReadOnlyModelViewSet
    rest_framework.viewsets
    ModelViewSet または
    rest_framework.generics
    CreateAPIView など
    どちらも APIView
    の⼦クラス
    rest_framework.views
    APIView
    GenericAPIView
    rest_framework.generics


    View Slide

  30. 1)APIView を継承したビューの書き⽅
    29
    コードは⻑くなるが、
    カスタマイズしやすい
    from rest_framework import status, views
    from rest_framework.generics import get_object_or_404
    from rest_framework.response import Response
    from shop.models import Book
    from .serializers import BookSerializer
    class BookRetrieveUpdateAPIView(views.APIView):
    """本モデルの取得(詳細)・更新・⼀部更新・削除APIクラス"""
    def get(self, request, pk, *args, **kwargs):
    """本モデルの取得(詳細)APIに対応するハンドラメソッド"""
    # モデルオブジェクトを取得
    book = get_object_or_404(Book, pk=pk)
    # シリアライザオブジェクトを作成
    serializer = BookSerializer(instance=book)
    return Response(serializer.data, status.HTTP_200_OK)
    def put(self, request, pk, *args, **kwargs):
    """本モデルの更新APIに対応するハンドラメソッド"""
    # モデルオブジェクトを取得
    book = get_object_or_404(Book, pk=pk)
    # シリアライザオブジェクトを作成
    serializer = BookSerializer(instance=book, data=request.data)
    # バリデーションを実⾏
    serializer.is_valid(raise_exception=True)
    # モデルオブジェクトを更新
    serializer.save()
    # レスポンスオブジェクトを作成して返す
    return Response(serializer.data, status.HTTP_200_OK)
    (以下略)
    api/views.py
    例えば更新 API では、モデルオブジェクトと
    ⼊⼒データからシリアライザオブジェクトを
    作成し、is_valid() で⼊⼒データのバリデー
    ションをおこない、save() でモデルオブジェ
    クトを更新して、最後にシリアライザの data
    属性の値を使ってレスポンスオブジェクトを
    作成して返す

    View Slide

  31. 2)汎⽤ APIView を継承したビューの書き⽅
    30
    • 対応アクションごとに汎⽤ APIView が
    ⽤意されている
    • queryset(モデルオブジェクトを取得する
    ためのクエリ)と serializer_class(シリ
    アライザクラス)と を指定するだけ
    from rest_framework import generics
    from shop.models import Book
    from .serializers import BookSerializer
    class BookListCreateAPIView(generics.ListCreateAPIView):
    """本モデルの取得(⼀覧)・登録APIクラス"""
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    class BookRetrieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
    """本モデルの取得(詳細)・更新・⼀部更新・削除APIクラス"""
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    api/views.py
    表7.汎⽤ APIView の種類と対応アクション
    from django.urls import path
    from api import views
    urlpatterns = [
    path('api/books/', views.BookListCreateAPIView.as_view()),
    path('api/books//', views.BookRetrieveUpdateDestroyAPIView.as_view()),
    ]
    config/urls.py
    (*) CreateAPIView では queryset は不要
    (*)

    View Slide

  32. 3)ModelViewSet 系ビューを継承したビューの書き⽅
    31
    • serializer_class と queryset の指定が必須
    • ViewSet ⽤の Router(SimpleRouter または
    DefaultRouter)を利⽤して URL パターンを
    URLconf に追加
    from rest_framework import viewsets
    from shop.models import Book
    from .serializers import BookSerializer
    class BookViewSet(viewsets.ModelViewSet):
    """本モデルのCRUD⽤APIクラス"""
    serializer_class = BookSerializer
    queryset = Book.objects.all()
    api/views.py
    from django.urls import include, path
    from rest_framework import routers
    from api import views
    router = routers.DefaultRouter()
    router.register('books', api.BookViewSet)
    urlpatterns = [
    # すべてのアクション(⼀覧・詳細・登録・更新・⼀部更新・削除)をまとめて追加
    path('api/', include(router.urls)),
    ]
    config/urls.py
    表8.ModelViewSet 系ビューの対応アクションメソッド
    単⼀モデルの CRUD を処理する REST API を
    まるっと実装したい場合に最適

    View Slide

  33. ポイント③ まとめ:起点は DRF ⽤ビュー
    32
    • 単⼀モデルの CRUD を処理する REST API をまるっと実装したい場合
    は、 ModelViewSet 系ビュー を使うのが⼀番簡単
    • ViewSet ⽤ Router と⼀緒に使う
    • 複雑なことがしたい場合は、APIView(または GenericAPIView)を
    継承したビュークラスを使う

    View Slide

  34. まとめ
    33
    ポイント①:全体像を把握しよう
    ポイント②:シリアライザはフォームっぽく使える
    ポイント③:起点は DRF ⽤ビュー
    『現場で使える
    Django REST Framework
    の教科書』
    (紙の本)
    (電⼦版)
    2022年12⽉ 改訂 !!
    Django 3.2 / DRF 3.14 対応、Vue 3 + Vuetify 3 でチュートリアル刷新
    DRF のことをもっと知りたい⽅は、この本がオススメ!!

    View Slide