Graph QL by facebook
처음 GraphQL에 대해 인식한 계기는, Graph DataBase 시연회에서 d3 대신 GraphQL로 시각화된 결과를 보면서 였다. 당시에는 D3, Chart Js 와 같은 시각화 도구인줄 알고서 어렵겠구나 하고 지나치고 있었는데, 직접적인 계기는 아래의 동영상을 보면서였다. RestAPI 에서 GraphQL로 넘어간 이유
당시 (지난주 ㅜㅜ.) Django 를 RestAPI로 연결하고, 이를 Vue.js 로 클라이언트 관리하는 작업을 목표로 자료들을 찾고 있었고 생각보다 제대로 된 자세한 설명들이 없어서 고생하던 중이었다.
결론적으로 graphql은 복잡하고 다양한 작업의 query를 처리하는데 적합하고, 파일전송 등 안정화된 작업에 있어서는 RestAPI가 강점이 있는 등 블로그 상호 보완적인 역활을 함을 알 수 있다.
내가 하려는 간단한 작업에는 GraphQL을 사용하는 방법으로도 충분할 것으로 보이므로, 작업을 하는데 있어서 GraphQL을 적극적으로 활용해 보도록 하자. 결국에는 관련된 자료를 찾기 쉬운 내용으로 진행을 하는게 현실이다. restAPI 와 React Js 로 자료들이 잘 되어 있다. 하지만 jQuery 쓰듯 vue.js를 활용하여 작업은 진전시키자
Graphene link
이 글을 작성하게 된 진짜 이유로써, 이 동영상이 짧으면서도 GraphQL이 Python에서 어떻게 작동하는지를 잘 알려주는 동영상으로써 정리하고자 함이다
Introduction
Python 기본 환경에서 Graphene을 사용하여 호출하는 방법을 실습한다
import graphene
# 질의용 Query 로 is_stuff 변수를 활용
class Query(graphene.ObjectType):
is_stuff = graphene.Boolean()
# info : graphene 연결변수
def resolve_is_staff(self, info):
return True
schema = graphene.Schema(query=Query)
query = "{ isStuff }"
result = schema.execute(query)
# print(result.data.items()) # raw 출력
items = dict(result.data.items())
print(items) # Query 출력
import json
print(json.dumps(items,indent=4)) # Json 출력
{
"isStuff": null
}
질의 변수를 CarmelCase로 정의한 경우 { is_stuff }
로 질의시 오류를 출력한다. 이를 사용하고 싶은 경우에는 scheme 객체를 schema = graphene.Schema(query=Query, **auto_camelcase=False**)
로 변경해야 한다.
Basic Filter (slicing)
DataBase 구조를 정의한다
class User(graphene.ObjectType):
id = graphene.ID()
username = graphene.String()
last_login = graphene.DateTime()
Query 객체를 정의한다
위에서 정의한 User() 클래스와 메서드로 구조화된 Query 질의문을 정의한다
from datetime import datetime
class Query(graphene.ObjectType):
users = graphene.List(User, first=graphene.Int())
def resolve_users(self, info, first):
return [
User(username='Alice', last_login=datetime.now()),
User(username='Bob', last_login=datetime.now()),
User(username='Steven', last_login=datetime.now()),
][:first]
사용자 정의 Query를 Test 한다
query3 = """ { users(first: 2) {
username
lastLogin } }"""
schema = graphene.Schema(query=Query)
result = schema.execute(query3)
items = dict(result.data.items())
print(json.dumps(items,indent=4))
{ "users": [
{ "username": "Alice",
"lastLogin": "2018-11-19T11:12:40.767433" },
{ "username": "Bob",
"lastLogin": "2018-11-19T11:12:40.767453" }, ] }
Mutations & Info
CRUD 와 같은 추가적인 기능을 작동하는 경우 아래의 부분 까지는 위와 동일하다
import graphene
from datetime import datetime
class User(graphene.ObjectType):
id = graphene.ID()
username = graphene.String()
last_login = graphene.DateTime(required=False)
class Query(graphene.ObjectType):
users = graphene.List(User, first=graphene.Int())
def resolve_users(self, info, first):
return [
User(username='Alice', last_login=datetime.now()),
User(username='Bob', last_login=datetime.now()),
User(username='Steven', last_login=datetime.now()),
][:first]
사용자 함수
추가적인 작업을 하는경우로써, mutate(self, **info**, username)
에서 info 매개변수는 사용자가 추가하는 설정들을 호출하는 용도로써 활용한다
class CreateUser(graphene.Mutation):
class Arguments:
username = graphene.String()
user = graphene.Field(User)
# mutate 내부에, 추가 mutate 정의
def mutate(self, info, username):
if info.context.get('is_vip'):
username = username.upper()
user = User(username=username)
return CreateUser(user=user)
class Mutations(graphene.ObjectType):
create_user = CreateUser.Field()
schema = graphene.Schema(query=Query, mutation=Mutations)
user_info = {'username':'Bob'}
info_items = {'is_vip': True }
# JSX 문법을 활용하여 동적인 Control이 가능하다
query4 = """
mutation createUser($username: String) {
createUser(username: $username){
user {
username
}
}
}"""
result = schema.execute(
query4,
variable_values=user_info,
context=info_items
)
items = dict(result.data.items())
print(json.dumps(items,indent=4))
{
"createUser": {
"user": {
"username": "BOB"
}
}
}
GraphQL 과 Django 연결
동영상에도 포함되어 있지만 단순 view기능 만 구현되어 있었다. 이 부분은 howtographql 에 정리된 내용을 통해서 추가적으로 정리해 보도록 한다