api 除了查詢功能外還需要寫入,在 graphql 裡面,寫入要用 Mutation。
回到我們的 schema 本體,把它改成:schema = graphene.Schema(query=Query, mutation=Mutation)
新增一個 Mutation class,整份 schema.py 現在長這樣:
import graphene
from collections import namedtuple 
from .schemaClass.playDataSchema import playDataSchema 
#---- 新增以下 ----------------------
from .mutations.writePlayData import writePlayData as writePlayDataMutation
#-----------------------------------
from api.api.playData import playData
from api.api.writePlayData import writePlayData
class Query(graphene.ObjectType):
    reverse = graphene.String(word=graphene.String(default_value='t'))
    def resolve_reverse(self, info, word):
        print(self)
        return 'hello'
    playData = graphene.List(playDataSchema, name = graphene.String())
    # playData = graphene.NonNull(playDataSchema, name = graphene.String())
    def resolve_playData(self, info, name):
        data = playData( {'name': name} )['data']
        if len(data) > 0:
            # --- 轉成 namedtuple ---
            outDataNT = namedtuple('myData', [ key for key in data[0] ])
            outData = [ outDataNT(**eachData) for eachData in data ]
            # ----------------------
            return outData
        else: 
            return []
#---- 新增以下 ----------------------
class Mutation(graphene.ObjectType):
    writePlayData = writePlayDataMutation.Field()
    def resolve_writePlayData(self, info):
        return writePlayDataMutation
        
#------------------------------------
schema = graphene.Schema(query=Query, mutation=Mutation)
在這次變動中,我們從 mutation 資料夾裡的 writePlayData 檔案中 import 了一個 Mutation 的 class,並把它命名為 writePlayDataMutation (現在還沒有這個檔案,我們等下再來創建它)。
然後新增了 Mutation 類別作為 mutation 的中樞,當使用者想要 writePlayData 時我們返回給它剛剛 import 的 mutation 類別, writePlayDataMutation.Field() 可以把它當成是將 mutation 類別降級成跟 string 類別一樣,才能放進 graphene.ObjectType 類別裡面。
__init.py 跟 writePlayData.py 。writePlayData.py 的內容如下:
import graphene
from api.api.writePlayData import writePlayData as writePlayDataFunc
class writePlayData(graphene.Mutation):
    class Arguments:
        name = graphene.String()
        lv = graphene.Int()
        skill = graphene.String()
    
    status = graphene.Boolean()
    err = graphene.String()
    def mutate(self, info, name, lv, skill):
        data = writePlayDataFunc( { 
            'name': name,
            'lv': lv, 
            'skill': skill
        } )
        status = data['status']
        err = data['err']
        return writePlayData(status=status, err=err)
writePlayDataFunc 是一隻可以寫入資料庫的 api 並且會返回 { status, err }, status 代表有沒有寫入成功。
接下來講解 graphene.Mutation 的架構:
在 mutation 這個類別裡,有三個元素
class writePlayData(graphene.Mutation):
# 第一個元素: 寫入所需要的參數-----------------
    class Arguments:
        name = graphene.String()
        lv = graphene.Int()
        skill = graphene.String()
#-------------------------------------------
# 第二個元素: 可以返回給使用者的資料 ----------
    status = graphene.Boolean()
    err = graphene.String()
#-------------------------------------------
# 第三個元素: 實際執行寫入,並回傳值 ----------
    def mutate(self, info, name, lv, skill):
        data = writePlayDataFunc( { 
            'name': name,
            'lv': lv, 
            'skill': skill
        } )
        status = data['status']
        err = data['err']
        return writePlayData(status=status, err=err)
              #注意這邊是 call 自己
#-------------------------------------------
在 mutation 裡面,class Arguments: 跟 def mutate(): 是必要的,沒有的話會報錯。
接下來 run 伺服器後就可以看到成果囉