DjangoでGraphQLを触ってみるPart.3 (データ操作編)

# はじめに
[DjangoでGraphQLを触ってみる Part.2](https://qiita.com/abemaru/items/cc862c548cdec65fa640)の続きです。
今回は、データの追加、削除、編集(Mutation)を実装します。

今回もdockerを使う前提で説明をします。詳しい内容は[私のgit](https://github.com/abemaru/my_graphql_demo)を参考にしてください。

# パート解説
### [Part1 : 入門向け環境構築と基本的な書き方](https://qiita.com/abemaru/items/fcd64145168e7267e615)
### [Part2 : GraphQLでリレーションなしの絞り込み実装](https://qiita.com/abemaru/items/cc862c548cdec65fa640)
### Part3 : データ追加、削除、編集(Mutation)の実装 ←イマココ

# 実装
## データ追加
まずはデータ追加を実装します。`.save()`を使うと簡単に実装できそうです。
```graphql_sample/schema.py
...

# create_itemの挙動
class CreateItem(graphene.Mutation):
    # 受け取る変数
    class Arguments:
        name = graphene.String()
        description = graphene.String()
        brand = graphene.String()
        user = graphene.Int()

    # 表示するもの
    item = graphene.Field(ItemType)

    # mutationの処理内容
    def mutate(root, info, name, description, brand, user):
        user = User.objects.get(pk=user)
        item = Item(name=name, description=description, brand=brand, user=user)
        item.save() # データ保存をしている場所
        return CreateItem(item=item)

# MyMutationの中にcreate_itemを追記
class MyMutation(graphene.ObjectType):
    create_item = CreateItem.Field()

...

# mutation=を追加することでmutationを実行できるようにする
schema = graphene.Schema(query=Query, mutation=MyMutation)
```
実装ができたらコンテナを立ち上げ、[localhost:8000/graphql](http://localhost:8000/graphql)にアクセスし以下を試す。
![スクリーンショット 2022-07-20 23.28.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326068/853e6ade-1a58-8bc6-815c-3448ea05e60b.png)
`mutation`を実行し`data`が帰ってきたら、`allItem`クエリでデータが追加されていることを確認しましょう。
![スクリーンショット 2022-07-20 23.31.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326068/f444bc52-aaee-1e25-70e9-c7ab66210766.png)

## データ削除
データ追加ができたらデータ削除も実装しましょう。データ追加と似て、`.delete()`でサクっと実装します
```graphql_sample/schema.py
... 
# delete_item実行時の挙動を追加
class DeleteItem(graphene.Mutation):
    class Arguments:
        name = graphene.String()

    ok = graphene.Boolean()

    def mutate(root, info, name):
        item = Item.objects.filter(name=name)
        item.delete() # ここの部分で削除
        return DeleteItem(ok=True)


class MyMutation(graphene.ObjectType):
    create_item = CreateItem.Field()
    delete_item = DeleteItem.Field() # deleteを追加
... 
```
実装したらまたコンテナを立ち上げます。`deleteItem`実行時に`ok: True`と帰ってきて、`allItem`で`Macbook Pro 16`が消えていれば成功です。
![スクリーンショット 2022-07-20 23.53.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326068/6ec1a25e-5e4e-bf15-a04a-dda8b8a3b246.png)
`Macbook Pro 16`が消えているので成功です！
![スクリーンショット 2022-07-20 23.53.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326068/3c1ed2f3-2df4-36f0-ecbe-4f6756028c70.png)

## データ編集
最後にデータの編集です。今回は、`Macbook Pro 14`の持ち主を変更したいと思います。
![スクリーンショット 2022-07-21 0.01.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326068/b0275d03-17d8-d7b6-7acf-c9134b28a73c.png)
またまた、`schema.py`を編集します。今回は`.update()`は使えなさそうだったので少し工夫します。

```graphql_sample/schema.py
# update_item_userの挙動を設定
class UpdateItemUser(graphene.Mutation):
    class Arguments:
        name = graphene.String()
        user = graphene.Int()

    ok = graphene.Boolean()

    def mutate(root, info, name, user):
        # 単純な.updateで実装できなかったため以下のように実装
        # バージョンによって違いはありそう
        obj, _ = Item.objects.get_or_create(
            name=name,
            user_id=user
        )
        return UpdateItemUser(ok=True)


class MyMutation(graphene.ObjectType):
    create_item = CreateItem.Field()
    delete_item = DeleteItem.Field()
    update_item_user = UpdateItemUser.Field() # MyMutationに追加し使えるようにする
```
実装ができたらコンテナに接続し、`updateItemUser`を実行し、`MacBook Pro 14`のuserを1から2に変更しましょう。
![スクリーンショット 2022-07-21 0.53.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326068/6ec2f2ae-94ca-d847-cc41-a8a2324525ec.png)
変更が反映されたら、`allItem`で一覧を取得し、`MacBook Pro 14`のuserが変更されていることが確認できれば成功です。
![スクリーンショット 2022-07-21 0.54.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326068/39dd08af-871f-6ecb-e736-2cc645842087.png)

# さいごに
ここまでgrapheneの機能をどんどん実装してきたが、クエリを叩くこともできるはずなのでPart4ではクエリのたたき方を確認する。