Django で GraphQL 実装してみた  リファクタ編

## Django で GraphQL 実装してみた
- [環境構築編](https://qiita.com/dbxkazuxdb/items/77a9c6d809a1c706e2db)
- [Query編](https://qiita.com/dbxkazuxdb/items/b1bdc9eac9856deb493c)
- [Mutation編](https://qiita.com/dbxkazuxdb/items/0d8e79cdba10349b47ec)
- リファクタ編 ← この記事  

### ディレクトリ
shemasフォルダを作成
その中に、NodeやQueryなどを記載していく

```bash
├── app
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── fixtures
│   │   └── ingredients.json
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── 0002_category_is_active.py
│   │   └── __init__.py
│   ├── models
│   │   ├── __init__.py
│   │   ├── category.py
│   │   └── ingredient.py
│   ├── schema.py
│   ├── schemas
│   │   ├── category.py
│   │   └── ingredient.py
│   ├── tests.py
│   └── views.py
├── config
│   ├── __init__.py
│   ├── asgi.py
│   ├── schema.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py
```
`app/models/__init__.py`
```python
from .category import Category
from .ingredient import Ingredient

__all__ = ["Category", "Ingredient"]

```

`app/schemas/category.py`
```python
from graphene import relay
from graphene_django import DjangoObjectType
from app.models import Category


class CategoryNode(DjangoObjectType):
    class Meta:
        model = Category
        interfaces = (relay.Node,)
        filter_fields = ["name", "ingredients", "is_active"]

```

`app/schemas/ingredient.py`
```python
import graphene
from graphene import relay, Mutation
from graphql_relay import from_global_id
from graphene_django import DjangoObjectType
from app.models import Ingredient, Category


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 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"])[1],
        )
        if input["name"]:
            ingredient.name = input["name"]
        if input["category_id"]:
            category = Category.objects.get(
                pk=from_global_id(input["category_id"])[1],
            )
            ingredient.category_id = category.id
        ingredient.save()
        return UpdateIngredient(ingredient=ingredient)
```

`app/schema.py`
```python
from graphene import relay
from graphene_django.filter import DjangoFilterConnectionField
from app.schemas.category import CategoryNode
from app.schemas.ingredient import IngredientNode, CreateIngredient, UpdateIngredient


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()

```

とりあえず、ある程度すっきりした
この辺りのアーキテクチャは、改めて考え直すことにする