#author("2019-11-13T11:33:53+00:00","","") #mynavi(); #setlinebreak(on); * 概要 [#h3339617] #html(<div style="padding-left: 10px;">) GraphQLはFacebookにより開発されたオープンソースの言語。 - Rest のようにリソース毎に複数のエンドポイントは持たない。(エンドポイントは1つ) - 事前定義されたスキーマとリクエスト時のクエリの内容に応じて処理が行われる などの特徴がある。 以降では、GraphQLサーバ環境の構築と簡単な動作確認を行う。 #html(</div>) * 目次 [#zefea870] #contents - 参考 -- https://graphql.org/learn/ -- https://docs.graphene-python.org/en/latest/quickstart/ -- https://github.com/graphql-python/graphene/blob/master/examples/simple_example.py - 関連 -- XXXXXXX * GraphQLの基礎 [#ia8c2b77] #html(<div style="padding-left: 10px;">) ** クエリとミューテーション [#ybc8a2b8] #html(<div style="padding-left: 10px;">) #TODO *** Fields [#pfa3b570] #html(<div style="padding-left: 10px;">) https://graphql.org/learn/queries/#fields #html(</div>) *** Arguments [#sff1c3fc] #html(<div style="padding-left: 10px;">) https://graphql.org/learn/queries/#arguments #html(</div>) *** Aliases [#cff67c85] #html(<div style="padding-left: 10px;">) https://graphql.org/learn/queries/#aliases #html(</div>) *** Fragments [#e76c2dce] #html(<div style="padding-left: 10px;">) https://graphql.org/learn/queries/#fragments #html(</div>) *** Operation Name [#b72b325a] #html(<div style="padding-left: 10px;">) https://graphql.org/learn/queries/#operation-name #html(</div>) *** Variables [#m597b6b7] #html(<div style="padding-left: 10px;">) https://graphql.org/learn/queries/#variables #html(</div>) *** Directives [#r00f8674] #html(<div style="padding-left: 10px;">) https://graphql.org/learn/queries/#directives #html(</div>) *** Mutations [#a59ea6e6] #html(<div style="padding-left: 10px;">) https://graphql.org/learn/queries/#mutations #html(</div>) *** Inline Fragments [#y9b73e9f] #html(<div style="padding-left: 10px;">) https://graphql.org/learn/queries/#inline-fragments #html(</div>) #html(</div>) // クエリとミューテーション ** スキーマとタイプ [#c745f6f1] #html(<div style="padding-left: 10px;">) #TODO *** Type System [#ze68b00b] #html(<div style="padding-left: 10px;">) #html(</div>) *** Type Language [#x3b3e0e0] #html(<div style="padding-left: 10px;">) #html(</div>) *** Object Types and Fields [#d5dacea4] #html(<div style="padding-left: 10px;">) #html(</div>) *** Arguments [#c5372518] #html(<div style="padding-left: 10px;">) #html(</div>) *** The Query and Mutation Types [#l8968084] #html(<div style="padding-left: 10px;">) #html(</div>) *** Scalar Types [#db6de978] #html(<div style="padding-left: 10px;">) #html(</div>) *** Enumeration Types [#ze5273d0] #html(<div style="padding-left: 10px;">) #html(</div>) *** Lists and Non-Null [#h9b08390] #html(<div style="padding-left: 10px;">) #html(</div>) *** Interfaces [#ze6d58f3] #html(<div style="padding-left: 10px;">) #html(</div>) *** Union Types [#wbc638e2] #html(<div style="padding-left: 10px;">) #html(</div>) *** Input Types [#ycab3418] #html(<div style="padding-left: 10px;">) #html(</div>) #html(</div>) #html(</div>) * サーバ側の環境構築 [#m4f52d38] #html(<div style="padding-left: 10px;">) pythonライブラリ graphene を使用してサーバ環境を構築する。 ** 準備 [#j4dcd023] #html(<div style="padding-left: 10px;">) pythonの仮想環境を作って graphene をインストールしておく。 ※WebAPIとして提供する為、flask と flask-graphql も同時にインストール。 #myterm2(){{ pip install pipenv pipenv --python 3.7 pipenv install graphene pipenv install flask pipenv install flask-graphql }} 動作確認用に仮想環境のシェルを起動しておく #myterm2(){{ pipenv shell }} #html(</div>) ** スキーマ 及び リゾルバ関数の定義 [#e2398928] #html(<div style="padding-left: 10px;">) schema.py #mycode2(){{ # サンプルデータ sample_users = { "1": {"id":1, "name":"Ichiro", "age":10}, "2": {"id":2, "name":"Jiro", "age":20}, "3": {"id":3, "name":"Saburo", "age":30} } class User(graphene.ObjectType): id = graphene.ID() name = graphene.String() age = graphene.Int() class Query(graphene.ObjectType): user = graphene.Field(User, id=graphene.ID()) users = graphene.Field(graphene.List(User)) def resolve_user(self, info, id): # resolve_変数名 """ID指定のユーザ取得.""" user_info = None if id: # if info.variable_values["id"] でも可 user_info = sample_users.get(id) # sample_users.get(info.variable_values["id"]) if user_info: return User(**user_info) else: return None def resolve_users(self, info, **kwargs): """ユーザ一覧の取得.""" return [ User(**sample_users[id]) for id in sample_users] class CreateUser(graphene.Mutation): class Arguments: name = graphene.String() age = graphene.Int() created = graphene.Boolean() user = graphene.Field(lambda: User) def mutate(root, info, name, age): id = len(sample_users) + 1 sample_users[str(id)] = {"id":id, "name":name, "age":age} user = User(id=id, name=name, age=age) return CreateUser(user=user, created=True) class MyMutations(graphene.ObjectType): create_user = CreateUser.Field() schema = graphene.Schema(query=Query, mutation=MyMutations) }} #html(</div>) ** スキーマ単体での動作確認 [#b2280a8e] #html(<div style="padding-left: 10px;">) test_schema.py #mycode2(){{ from schema import schema if __name__ == "__main__": # ユーザを作成 query = """ mutation createMutation { createUser(name:"Shiro", age:40) { user { id name age } created } } """ result = schema.execute(query) print(result.data) # 一覧を取得 query = """ query ListQuery { users { id, name, age } } """ result = schema.execute(query) print(result.data) # IDを指定して取得 query = """ query SampleQuery($id: ID) { user(id: $id) { id, name, age } } """ result = schema.execute(query, variable_values={"id": 3}) print(result.data) }} 動作確認の実行 #myterm2(){{ python test_schema.py OrderedDict([('createUser', OrderedDict([('user', OrderedDict([('id', '4'), ('name', 'Shiro'), ('age', 40)])), ('created', True)]))]) OrderedDict([('users', [OrderedDict([('id', '1'), ('name', 'Ichiro'), ('age', 10)]), OrderedDict([('id', '3'), ('name', 'Saburo'), ('age', 30)]), OrderedDict([('id', '2'), ('name', 'Jiro'), ('age', 20)]), OrderedDict([('id', '4'), ('name', 'Shiro'), ('age', 40)])])]) OrderedDict([('user', OrderedDict([('id', '3'), ('name', 'Saburo'), ('age', 30)]))]) }} #html(</div>) ** Webサーバの実装 [#n51fc439] #html(<div style="padding-left: 10px;">) app.py #mycode2(){{ from schema import schema from flask import Flask from flask_graphql import GraphQLView app = Flask(__name__) app.debug = True app.add_url_rule( '/', view_func=GraphQLView.as_view( 'graphql', schema=schema, graphiql=True # テスト時などにブラウザから利用できるAPIコンソールをONにしておく ) ) if __name__ == '__main__': app.run() }} サーバ起動 #myterm2(){{ python app.py }} #html(</div>) ** WebAPIとしての動作確認 [#td188c56] #html(<div style="padding-left: 10px;">) #myterm2(){{ # 一意検索 curl http://127.0.0.1:5000/ --data query='query { user(id: "1") { id, name, age}}' {"data":{"user":{"id":"1","name":"Taro","age":20}}} # 一覧検索 curl http://127.0.0.1:5000/ --data query='query { users{ id, name}}' {"data":{"users":[{"id":"3","name":"Saburo"},{"id":"1","name":"Ichiro"},{"id":"2","name":"Jiro"}]}} # 追加 curl http://127.0.0.1:5000/ --data query='mutation { createUser(name:"Shiro", age:40) { user {id, name, age}, created }}' {"data":{"createUser":{"user":{"id":"4","name":"Shiro","age":40},"created":true}}} }} 尚、graphiql=True で起動している場合は、ブラウザから任意のQueryを発行する為のコンソール画面も提供されるので、そちらから確認する事も可能。 #html(</div>) #html(</div>)