DjangoではじめるGraphQLとフロントエンド開発の協業

 DjangoではじめるGraphQLとフロントエンド開発の協業

DjangoCongress JP 2019発表資料

1d42b38276c3d2c7cc931fa444c13488?s=128

Masaya Nasu

May 18, 2019
Tweet

Transcript

  1. DjangoではじめるGraphQLと フロントエンド開発の協業 DjangoCongress JP 2019 2019.05.18 GitHub @nasum Twitter @tomato360

  2. 自己紹介 那須理也 Twitter:@tomato360 https://twitter.com/tomato360 GitHub:@nasum https://github.com/nasum 所属:LAPRAS株式会社

  3. None
  4. None
  5. なんでGraphQL?

  6. Githubが2017年にAPI v4に採用 > Why GitHub is using GraphQL > GitHub

    chose GraphQL for our API v4 because it offers significantly more flexibility for our integrators. The ability to define precisely the data you want—and only the data you want—is a powerful advantage over the REST API v3 endpoints. GraphQL lets you replace multiple REST requests with a single call to fetch the data you specify. > GitHubは、API v4にGraphQLを選択しました。インテグレータにとって、柔軟性が大 幅に向上するためです。必要なデータ(および必要なデータのみ)を正確に定義できるこ とは、REST API v3エンドポイントを超える強力な利点です。 GraphQLでは、指定した データを取得するために、複数のREST要求を単一の呼び出しに置き換えることができ ます。 https://developer.github.com/v4/
  7. 2018年11月 GraphQL Foundation設立

  8. None
  9. 機は熟した(個人の感想です)

  10. 学びたいが自分の領域に近いところで 学びたい

  11. 最近仕事で使っているのはDjango

  12. そこでGraphene-Django

  13. 今日話すこと • GraphQLの基礎 • graphene-djangoの紹介 • graphene-djangoを使ったWebアプリケーションの開発 ◦ バックエンドにgraphene-django ◦

    フロントエンドにvue-apollo ◦ うまく連携させる • GraphQL雑感(個人の意見です)
  14. GraphQLの基礎

  15. GraphQLとは • WebAPIのための規格 ◦ クエリ言語とスキーマからなる • 2015年にFacebookが仕様を公開 • 現在はGraphQL Foundationでメンテナンスされている

  16. REST APIと比べて優れていること • エンドポイントが1つになる • 1リクエストで必要なデータを全て取得できる ◦ RESTだと複数APIを叩いて1ページを構築しがち • スキーマファーストな開発が出来る

    ◦ フロントとバックエンドの開発を非同期に行える • スキーマに型が定義出来る ◦ みんな型欲しいよね?私は欲しいです
  17. type Ship { id: ID! name: String! shipType: ShipType! }

    type Organization { id: ID! name:String! ships: [Ship] } type Query { ships(name: String, shipType: ShipType): [Ship!]! organizations(name: String): [Organization!]! } APIを定義するスキーマ 型の定義 クエリの定義
  18. データを取得するためのQuery クエリの実行 { "data": { "ships": [ { "name": "aoba",

    "shipType": "HEAVY_CRUISER" } ] } } query ships { ships { name shipType } }
  19. データを更新するためのMutation Mutationの実行 mutation newShip { createShip(input:{name:"aoba", shipType: HEAVY_CRUISER}) { id

    name shipType } } { "data": { "createShip": { "id": "乱数", "name": "aoba", "shipType": "HEAVY_CRUISER" } } }
  20. GraphQLには他にもいろいろな機能がある • 共通フィールドを定義できるinterface • 返値にいずれかの型を指定できるunion • クエリとべつに渡すことがができるVariables • メタデータを与えられるDirective

  21. まずはGitHubのAPIで試してみる(デモ) https://developer.github.com/v4/explorer/

  22. graphene-djangoの簡単な紹介

  23. None
  24. スポンサーがいないのが 若干気になるが・・・

  25. ドキュメントが豊富で安心感がある

  26. graphene-djangoの特徴 • Pythonのコードでスキーマを構築する • graphiqlが簡単に使える • relayを使う場合便利(未検証)

  27. サンプル from django.db import models from graphene_django import DjangoObjectType import

    graphene class UserModel(models.Model): name = models.CharField(max_length=100) last_name = models.CharField(max_length=100) class User(DjangoObjectType): class Meta: model = UserModel class Query(graphene.ObjectType): users = graphene.List(User) def resolve_users(self, info): return UserModel.objects.all() schema = graphene.Schema(query=Query) https://github.com/graphql-python/graphene-django/#examples
  28. graphiqlが簡単に使える urlpatterns = [ path('admin/', admin.site.urls), path('', TemplateView.as_view(template_name='index.html')), path('graphql/', GraphQLView.as_view(graphiql=True)),

    ] + static(settings.STATIC_URL) Trueにするとgraphiqlが使える
  29. relayと組み合わせると便利 ./manage.py graphql_schema --out schema.json • babel-relay-pluginで読み込めるスキーマが出力できる • react-relayとかで組み合わせると良さそう

  30. Graphene-Djangoを使った Webアプリケーション開発

  31. クイズアプリの実装

  32. クイズアプリの実装 https://quiz-l.herokuapp.com/ https://github.com/nasum/quiz

  33. 使用技術等 • django • graphene-django • vue-apollo(!)

  34. まずはバックエンドの開発

  35. モデル作成 from django.db import models class Terms(models.Model): title = models.CharField(max_length=256)

    def __str__(self): return self.title
  36. GraphQLのスキーマを作成する # 型の作成 class TermType(DjangoObjectType): class Meta: model = Terms

    id = graphene.ID() title = graphene.String() questions = graphene.List(QuestionsType)
  37. リゾルバの作成 class Query(graphene.ObjectType): term = graphene.Field(TermType, id=graphene.ID()) terms = graphene.List(TermType)

    def resolve_term(self, info, id): return Terms.objects.get(pk=id) def resolve_terms(self, info): return Terms.objects.all() 各フィールドに対応する 関数を定義する djangoのormを使用して書ける
  38. 登録する schema = graphene.Schema(query=Query)

  39. Mutationの作成 class CreateTerm(graphene.Mutation): term = graphene.Field(TermType) question = graphene.Field(QuestionsType) answer

    = graphene.Field(AnswersType) class Arguments: title = graphene.String(required=True) questions = graphene.List(QuestionsInputType) クラス名がMutationの名前になる
  40. Mutationの作成 def mutate(self, info, title, questions): term = Terms.objects.create(title=title) for

    question in questions: question_obj = Questions.objects.create( terms=term, description=question.description ) # 略 return CreateTerm(term=term) Argumentフィールドに定義した変数が 引数として渡される
  41. Mutationの作成 class MyMutations(graphene.ObjectType): create_term = CreateTerm.Field() schema = graphene.Schema( query=Query,

    mutation=MyMutations )
  42. ここまでくるとGraphiQLで確認できる https://quiz-l.herokuapp.com/graphql/

  43. これでバックエンドはできた

  44. 次はフロント

  45. None
  46. vue-apollo • Vue.jsでapollo-clientを使いやすくするPlugin • VueCLIで簡単に入れることが出来る ◦ vue add apollo •

    Vue.jsでGraphQLをやるときおそらく一番使いやすい
  47. apollo-clientが便利 • データの取得等をほとんど任せられる ◦ axiosなどのhttp requestのためのライブラリは内包している • キャッシュの仕組みやリロード周りも設定を書ける • WebSocketにも対応している

    • データソースはGraphQLサーバー相手でなくても良い ◦ localstorageとかもクエリすることが出来る
  48. vue-apolloを使ったクエリの実行方法 export default Vue({ name: 'Index', apollo: { terms: gql`query{

    terms { id, title } }` } }) graphql-tagが提供しているテ ンプレートリテラルのタグ クエリをパースしている。 this.termsでアクセス出来る ようになる
  49. methods: { async register() { const result = await this.$apollo.mutate({

    // Query mutation: gql`mutation ($title: String!, $questions: [QuestionsInputType]){ createTerm(title: $title, questions: $questions) { term { title } } }`, // Parameters variables: { title: this.title, questions: this.questions }, }) } } Mutationの実行方法 mutationのクエリ(?)をかく クエリ内のパラメータを定義
  50. フロントも完成

  51. https://quiz-l.herokuapp.com/

  52. GraphQL&graphene-django雑感

  53. ツールがそろっていて開発はしやすい • GraphiQLが簡単に使える • ドキュメントが豊富 • relayと組み合わせるとさらによさそう(検証できてない • apollo-clientを使えばクエリもミューテーションも簡単 •

    逆に言えばライブラリありきではある ◦ でもWeb開発ってだいたいそんな感じだと思う
  54. Pythonのコードでスキーマを書くのに少し違和感 • スキーマは本来コードと関係ないはず ◦ あくまで仕様だから • スキーマを書いたらそこからコードを出力して欲しい ◦ golangのライブラリがその辺いい感じに解決している(余談 https://github.com/99designs/gqlgen

  55. DDDとかやりにくそう • djangoのモデルにがっつり結びついている ◦ インフラ層の事情がそのままアプリケーション層に影響する ◦ リゾルバで工夫すればうまくいくかも? • 素のgrapheneを使うといいかもしれない •

    用法用量はよく考えましょう(虹色の解釈
  56. とはいえ

  57. 使ってみて結構便利さを感じたのも事実 • APIのエンドポイントと仕様を考えないでいい ◦ エンドポイントは1つ ◦ 仕様はコードにあるし型もつく • graphiqlがとにかく便利 •

    vue-apolloなどapollo関連の技術を使うととても楽
  58. 多分残り続ける技術なので 個人サービスで素振りをすれば 良いんじゃないかな?

  59. おしまい