Successfully reported this slideshow.
Your SlideShare is downloading. ×

実践!Django + GraphQL 実装

Check these out next

1 of 62 Ad
1 of 62 Ad
Advertisement

More Related Content

Similar to 実践!Django + GraphQL 実装 (20)

Advertisement

実践!Django + GraphQL 実装

  1. 1. 実践!Django + GraphQL実装 kai ~素敵なGraphQL Tipsを添えて~
  2. 2. おまえだれよ ● kai(甲斐 光彦) ● 株式会社 所属 ● kaiは携わってないけれど が提供しているサービス達
  3. 3. こんな経験ありませんか?(1/3) ● PC/Mobileへの対応が必要な昨今 ● 必要なデータはクライアントの種別毎に変わる
  4. 4. こんな経験ありませんか?(2/3)
  5. 5. こんな経験ありませんか?(3/3)
  6. 6. GraphQLについて(1/2) ● GraphQLとはクエリ言語 ○ スキーマを定義する ○ GraphQLで扱う全てのデータ・処理の入力/返却値の型を定義する ○ resolverを用意してリクエストを処理する ● エンドポイントが一つ ○ 今回の資料では /graphql ● 1つのリクエストで、必要な情報を選んで全て取得する ○ クライアントサイドでクエリを書いて取得するデータを自由に取得できる
  7. 7. ● Query ○ GET相当の処理 ● Mutation ○ POST相当の処理 ● Subscription ○ WebSocketを使った処理 GraphQLについて(2/2)
  8. 8. ほげおとの出会い〜仕事の依頼〜
  9. 9. ● Graphene-Django ○ graphene-pythonをdjangoで利用するためのライブラリ ● Graphene-Subscription ○ subscriptionを利用するためのライブラリ ● strawberry ○ Dataclassを使ったType定義 ○ ここ最近活発 ● Ariadne ○ スキーマファーストアプローチで開発を進める事を主眼に置いている GraphQL + Python関連ライブラリ
  10. 10. ● 本屋さんのシステム ● settings.pyを編集 プロジェクトの用意
  11. 11. ● 書籍 ● 著者 ● 書籍-著者 ● 判型 モデル/データの用意 書籍 判型 著者 書籍-著者
  12. 12. ● アプリ毎スキーマファイルが存在 ● ルートスキーマでまとめる ● (urls.pyと同じ要領) Grapheneの設定(1/3)
  13. 13. ● bookstore/urls.pyにエンドポイントを設定する Grapheneの設定(2/3)
  14. 14. ● settings.pyにルートスキーマの設定をする ● それではQueryの実装に進みましょう! Grapheneの設定(3/3)
  15. 15. ● books/schema.py ● Type作成 Queryの作成 ~ GraphQL Typeの作成
  16. 16. ● Queryクラスに各Queryを記述する ● 返り値の定義 Queryの作成 ~ booksクエリの作成
  17. 17. ● Queryクラスbooksクエリのresolverを作成する Queryの作成 ~ booksクエリの作成
  18. 18. ● ルートスキーマ(bookstore/schema.py)にbooksのスキーマを反映する ● まとめたQueryを作成しSchemaに渡す ○ Mutation, Subscriptionも実装したら同様にルートスキーマに反映していく Queryの作成 ~ ルートスキーマの定義
  19. 19. ● runserverしたら /graphql にブラウザでアクセス! GraphiQLの使い方 (1/3)
  20. 20. ● 利用可能なAPI情報が閲覧できる ○ 入力型 ○ 出力型 ○ 取得可能なデータ GraphiQLの使い方 (2/3)
  21. 21. ● キーワード引数で引数名と型を指定する Queryの作成 ~ 引数を追加する(1/2)
  22. 22. ● resolverにtitle引数を追加 Queryの作成 ~ 引数を追加する(2/2)
  23. 23. Queryの実装完了 ● ここでリリースしてほげおさんに動作確認依頼
  24. 24. カスタムフィールドの追加
  25. 25. 調査 ● ステージング環境にはbookとauthorのレコードが大量が用意されていた ● ログを確認した所、booksクエリでauthorも一緒に取得していた! ● → N+1が発生してパフォーマンスが低下してタイムアウト!
  26. 26. ● 盛大なN+1問題が発生しないようにする・READのパフォーマンスを上げる ○ クライアントから無限に結合が可能なので注意する ○ 利用するケースの把握を行って適宜N+1対策を講じる ○ graphene-django-optimizer を使う ○ 自動的にselect_related, prefetch_related, onlyを指定する ○ よく利用する部分に関してはINDEXを貼る ● 取得されたくないテーブルはTypeを追加しない ○ MBookSizeはTypeを追加していないので取得できない ● 取得されたくないカラムはexcludeする ○ Typeクラスに定義する ○ exclude = ("title",) Queryを作成する前に知っておきたい事 (1/2)
  27. 27. ● 不要な逆参照は作らない ○ related_name="+" ○ 予期しないN+1が発生したり, 無駄な結合が起きたり Queryを作成する前に知っておきたい事 (2/2) 一年後のER図(イメージ) 初期のER図
  28. 28. 次のタスク
  29. 29. ● 書籍新規登録APIを作成しましょう ● MutationとはRESTで言うところPOSTでしたね ● Django FormやDRFのSerializerを使うことができます ○ 今回はDjango Form使います Mutationの作成
  30. 30. ● ModelFormを使ってみましょう Mutationの作成
  31. 31. ● ModelFormを使ってみましょう Mutationの作成
  32. 32. ● 入力の型を作成します ● InputObjectTypeのものを指定すればネストを表現できる MutationのInputTypeを作成
  33. 33. ● 入力の型を作成します ● InputObjectTypeのものを指定すればネストを表現できる MutationのInputTypeを作成
  34. 34. Mutationの作成
  35. 35. ● GraphQLスキーマをアウトプットする モックサーバを用意する(1/2)
  36. 36. ● npm i graphql apollo-server ● main.jsに以下の記述をしてnode main.js モックサーバを用意する(2/2)
  37. 37. ● python manage.py graphql_schemaでjson形式で型が出力される ● TypeScriptの型として利用可能にするとフロントと型を一致して扱えるので 便利 ちなみに……
  38. 38. ● Formを作成する Mutationの作成続き
  39. 39. ● mutateメソッドを作成 ● ルートスキーマにMutationを反映する Mutationの作成
  40. 40. Mutationの動作確認
  41. 41. ● graphqlパッケージにGraphQLErrorが存在するので使う ● 発生した時点でレスポンスが返る 例外処理
  42. 42. ● deprecatedなAPIはdeprecation_reasonを書く ○ Docsに反映されます ブレイクタイム
  43. 43. ● 新規登録された書籍をリアルタイムで画面側に反映させたいらしい バグじゃないですが、やります
  44. 44. ● WebSocketを使ったリアルタイムな処理を行う ○ 通知や新たに追加されたデータの更新など ● 登場する技術 ○ graphene-subscriptions, channel, RxPy, (Redis) Subscriptionとは
  45. 45. ● pip install graphene-subscriptions ● settings.pyの設定 graphene-subscriptionsの設定
  46. 46. ● routing.pyの作成 graphene-subscriptionsの設定
  47. 47. ● Signalを検知できるようにする(books/signals.py) Subscriptionの実装
  48. 48. ● Signalを検知できるようにする(books/apps.py) Subscriptionの実装
  49. 49. ● books/schema.pyにSubscriptionを追加する Subscriptionの実装
  50. 50. Subscriptionの実装
  51. 51. ● ルートスキーマにSubscriptionを追加しましょう ● SubscriptionはWebSocketのサーバを立ち上げる必要があるのでdaphne等を 使いましょう ○ 今回使うコマンド: daphne -b 0.0.0.0 -p 8000 bookstore.asgi:application ● 動作確認時はrunserverと違って静的ファイルもサーブする必要があります ○ Serving static files during developmentを参考にcollectstaticしてサーブしましょう 動作確認の前に確認!
  52. 52. ● 実行すると待ちの状態になるので、適当に作成してみると 動作確認の前に確認!
  53. 53. ● Mutation実行時に作成したレコードの情報が送られてくる 動作確認
  54. 54. ● 任意のタイミングでシグナルを送る方法について ほげおからの都合の良い質問
  55. 55. ● ModelSubscriptionEvent, SubscriptionEventを使う 任意のタイミングでシグナルを発火する
  56. 56. 任意のタイミングでシグナルを発火する
  57. 57. ほげおとの別れ〜そして検収へ〜 この物語はフィクションであり、実在の人物・団体・事件とは一切関係ありません
  58. 58. おわりに ● 自由に値を取得できるのは便利 ○ 反面、大変なこともあるけど…… ● クライアントが複数存在しているようなケースではGraphQLは有用 ○ RESTで構築してきたAPIがあっても、一部だけGraphQLから始めるもOK ● DjangoでGraphQLのQuery, Mutation, Subscriptionを使ってみよう! ● 謝辞(感謝っ圧倒的感謝っ) ○ レビュアーのみなさん: furuta, furi ○ 同僚のみなさん: james, kemu, ssh22

×