6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

GraphQL Clientの使い方

Posted at

はじめに

  • GraphQLの勉強のため、以下のサイトのfull-stack tutorialをやってみた。
  • https://www.apollographql.com/docs/tutorial/introduction/
  • サーバー側はなんとか理解したが、クライアント側がReactベースで全く分からない。
  • 代わりにPythonからGraphQL Clientを使用してみた。

GraphQLサーバーの起動

cd fullstack-tutorial\final\server
npm run start
http://127.0.0.1:4000/

スキーマ定義

  • LaunchConnection.cursorは、打ち上げデータに付与されているlaunch_date_unixに対応。
  • Mission.missionPatchは、打ち上げに対応するアイコン画像情報。大と小があり、デフォルトは大。
  • User.tokenは、ここではemailをbase64エンコーディングしたもの。
type Query {
  launches(
    """
    The number of results to show. Must be >= 1. Default = 20
    """
    pageSize: Int
    """
    If you add a cursor here, it will only return results _after_ this cursor
    """
    after: String
  ): LaunchConnection!
  launch(id: ID!): Launch
  me: User
}

type Mutation {
  # if false, signup failed -- check errors
  bookTrips(launchIds: [ID]!): TripUpdateResponse!

  # if false, cancellation failed -- check errors
  cancelTrip(launchId: ID!): TripUpdateResponse!

  login(email: String): User
}

type TripUpdateResponse {
  success: Boolean!
  message: String
  launches: [Launch]
}

"""
Simple wrapper around our list of launches that contains a cursor to the
last item in the list. Pass this cursor to the launches query to fetch results
after these.
"""
type LaunchConnection {
  cursor: String!
  hasMore: Boolean!
  launches: [Launch]!
}

type Launch {
  id: ID!
  site: String
  mission: Mission
  rocket: Rocket
  isBooked: Boolean!
}

type Rocket {
  id: ID!
  name: String
  type: String
}

type User {
  id: ID!
  email: String!
  profileImage: String
  trips: [Launch]!
  token: String
}

type Mission {
  name: String
  missionPatch(size: PatchSize): String
}

enum PatchSize {
  SMALL
  LARGE
}

PythonからGraphQL Clientを使用

import json

from gql import gql, Client
from gql.transport.aiohttp import AIOHTTPTransport

transport = AIOHTTPTransport(url="http://127.0.0.1:4000/")
client = Client(transport=transport)

# 打ち上げ予定の一覧を取得 (名前をlaunchesからpageに変更)
query = gql("""
    query GetLaunches {
      page: launches(pageSize: 3) {
        cursor
        hasMore
        launches {
          id
          mission {
            name
            missionPatch(size: SMALL)
          }
        }
      }
    }
""")

result = client.execute(query)
print(json.dumps(result, indent=2))
{
  "page": {
    "cursor": "1605486420",
    "hasMore": true,
    "launches": [
      {
        "id": "109",
        "mission": {
          "name": "Starlink-15 (v1.0)",
          "missionPatch": "https://images2.imgbox.com/9a/96/nLppz9HW_o.png"
        }
      },
      {
        "id": "108",
        "mission": {
          "name": "Sentinel-6 Michael Freilich",
          "missionPatch": null
        }
      },
      {
        "id": "107",
        "mission": {
          "name": "Crew-1",
          "missionPatch": "https://i.imgur.com/BzaSAnx.png"
        }
      }
    ]
  }
}
# ログインしてトークンを取得
query = gql("""
    mutation LoginUser {
      login(email: "daisy@apollographql.com") {
        token
      }
    }
""")

result = client.execute(query)
print(json.dumps(result, indent=2))
{
  "login": {
    "token": "ZGFpc3lAYXBvbGxvZ3JhcGhxbC5jb20="
  }
}
# ヘッダーを設定したclientを作成
headers = {'authorization': 'ZGFpc3lAYXBvbGxvZ3JhcGhxbC5jb20='}
transport = AIOHTTPTransport(url="http://127.0.0.1:4000/", headers=headers)
client = Client(transport=transport)

# 打ち上げの予約
query = gql("""
    mutation BookTrips {
      bookTrips(launchIds: [67, 68, 69]) {
        success
        message
        launches {
          id
        }
      }
    }
""")

result = client.execute(query)
print(json.dumps(result, indent=2))
{
  "bookTrips": {
    "success": true,
    "message": "trips booked successfully",
    "launches": [
      {
        "id": "67"
      },
      {
        "id": "68"
      },
      {
        "id": "69"
      }
    ]
  }
}
# 打ち上げのキャンセル
query = gql("""
    mutation BookTrips {
      cancelTrip(launchId: 68) {
        success
        message
        launches {
          id
        }
      }
    }
""")

result = client.execute(query)
print(json.dumps(result, indent=2))
{
  "cancelTrip": {
    "success": true,
    "message": "trip cancelled",
    "launches": [
      {
        "id": "68"
      }
    ]
  }
}
# ユーザーの情報と予約している打ち上げを取得
query = gql("""
    query {
      me {
        email
        trips {
          id
          mission {
            name
            missionPatch
          }
        }
      }
    }
""")

result = client.execute(query)
print(json.dumps(result, indent=2))
{
  "me": {
    "email": "daisy@apollographql.com",
    "trips": [
      {
        "id": "67",
        "mission": {
          "name": "Merah Putih",
          "missionPatch": "https://images2.imgbox.com/a8/f5/ZgdsrbqW_o.png"
        }
      },
        "id": "69",
        "mission": {
          "name": "SAOCOM 1A",
          "missionPatch": "https://images2.imgbox.com/66/d2/oVB1ofaZ_o.png"
        }
      }
    ]
  }
}

その他

  • SQLite3では、INTEGER型のカラムに対してPRIMARY KEY制約を設定すると、自動インクリメントとなる。
  • Sequelize ORMを使用すると、テーブルのカラムにcreatedAtとupdatedAtが追加される。
  • データベースの更新処理は非同期で実行される。
6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?