Django で GraphQL 実装してみた
実装
createメソッド追加
app/schema.py
class IngredientNode(DjangoObjectType):
class Meta:
model = Ingredient
interfaces = (relay.Node,)
filter_fields = {
"name": ["exact", "icontains", "istartswith"],
"notes": ["exact", "icontains"],
"category": ["exact"],
"category__name": ["exact"],
"category__is_active": ["exact"],
}
+ class CreateIngredient(Mutation):
+ class Arguments:
+ name = graphene.String(required=True)
+ category_id = graphene.ID(required=True)
+
+ ingredient = graphene.Field(IngredientNode)
+
+ def mutate(self, info, **input):
+ ingredient = Ingredient(
+ name=input["name"],
+ category_id=input["category_id"],
+ )
+ ingredient.save()
+ return CreateIngredient(ingredient=ingredient)
class Query:
category = relay.Node.Field(CategoryNode)
categories = DjangoFilterConnectionField(CategoryNode)
ingredient = relay.Node.Field(IngredientNode)
ingredients = DjangoFilterConnectionField(IngredientNode)
+ class Mutation:
+ create_ingredient = CreateIngredient.Field()
create mutation実行
createIngredientの中に、queryで取得したい値を指定することができる。
mutation{
createIngredient(name:"new item name", categoryId:"1"){
ingredient{
id
name
category {
id
name
}
}
}
}
relayのIDを解決する
idは、base64エンコードされるため、DBに保存する際は本来の値を保存したい。
from_global_idメソッドを使用する。
戻り値は(type, id)
typeは、DjangoObjectTypeのクラス名、idはDBの値
※今回の場合、typeはIngredientNode
となる
app/schema.py
+ from graphql_relay import from_global_id
...
class CreateIngredient(Mutation):
class Arguments:
name = graphene.String(required=True)
category_id = graphene.ID(required=True)
ingredient = graphene.Field(IngredientNode)
def mutate(self, info, **input):
+ category_node = from_global_id(input["category_id"])
ingredient = Ingredient(
name=input["name"],
- category_id=input["category_id"],
+ category_id=category_node.id,
)
ingredient.save()
return CreateIngredient(ingredient=ingredient)
updateメソッド追加
app/schema.py
class CreateIngredient(Mutation):
class Arguments:
name = graphene.String(required=True)
category_id = graphene.ID(required=True)
ingredient = graphene.Field(IngredientNode)
def mutate(self, info, **input):
ingredient = Ingredient(
name=input["name"],
category_id=input["category_id"],
)
ingredient.save()
return CreateIngredient(ingredient=ingredient)
+ class UpdateIngredient(Mutation):
+ class Arguments:
+ id = graphene.ID(required=True)
+ name = graphene.String()
+ category_id = graphene.String()
+
+ ingredient = graphene.Field(IngredientNode)
+
+ def mutate(self, info, **input):
+ ingredient = Ingredient.objects.get(
+ pk=from_global_id(input["id"]).id,
+ )
+ if input["name"]:
+ ingredient.name = input["name"]
+ if input["category_id"]:
+ node = from_global_id(input["category_id"])
+ ingredient.category_id = node.id
+
+ ingredient.save()
+ return UpdateIngredient(ingredient=ingredient)
class Query:
category = relay.Node.Field(CategoryNode)
categories = DjangoFilterConnectionField(CategoryNode)
ingredient = relay.Node.Field(IngredientNode)
ingredients = DjangoFilterConnectionField(IngredientNode)
class Mutation:
create_ingredient = CreateIngredient.Field()
+ update_ingredient = UpdateIngredient.Field()
update mutation実行
mutation {
updateIngredient(id:"SW5ncmVkaWVudE5vZGU6MQ==", name:"update", categoryId:"Q2F0ZWdvcnlOb2RlOjE="){
ingredient {
id
name
category {
id
name
}
}
}
}
次は、リファクタ編