「初心者向け」Python（Django）でGraphQLでデータ取得できるまで

## 前提

###目指したもの：

Django初学者がGraphQLを利用できる環境構築まで

### 開発環境：

* Python　：3.8
* Django　：3.2.7
* graphene：2.1.9

## 前準備

今回の環境（ディレクトリ）を用意

```
mkdir newsite
cd newsite
```

まだ、ディレクトリが１つあるだけのシンプルな状態

```
.
└newsite (current directory)
```


### プロジェクトを作成する

次のコマンドを叩くと、

```
django-admin startproject myproject
```

カレントディレクトリに myproject ディレクトリとその配下のファイル群が自動作成されます

```
.
└newsite
 └myproject
  └myproject
   ├myproject
   ├db.sqlite3
   └manage.py
```


### 開発サーバーの起動

manage.pyが存在するディレクトリまで移動し

```
cd myproject
```

下記サーバーを起動するコマンドを実行

```
python manage.py runserver
```

migrationでエラーが出ますが、このタイミングでは無視して問題ありません。

続いてこちらのＵＲＬを開く「http://127.0.0.1:8000/」

『The install worked successfully! Congratulations!』が表示される画面が開かれれば、ここまでは成功です


### アプリケーションを作成する

続いてアプリケーションを作成するコマンドを打ちます。

```
python manage.py startapp myapplication
```

新しくmyappというフォルダとファイル群が生成されるハズです。

```
.
└newsite
 └myproject
　├myapplication ← New!
  └myproject
   ├myproject
   ├db.sqlite3
   └manage.py
```

#### 設定

設定ファイルにアプリケーションを関連付けます
＋スキーマの場所もね

```
# myproject/settings.py

# sample project application
INSTALLED_APPS += [
    'graphene_django', # 追加
    'myapplication', # 追加
]

GRAPHENE = {
    'SCHEMA': 'myproject.schema.schema'
}
```

#### モデルの定義

```
# myproject/myapplication/models.py

from django.db import models
from django.utils import timezone

class Mountains(models.Model):
    id = models.BigAutoField(primary_key=True)
    name = models.CharField(max_length=255, blank=True, null=True)
    height = models.IntegerField(blank=True, null=True)
    lat = models.FloatField(blank=True, null=True)
    lon = models.FloatField(blank=True, null=True)

    def __str__(self):
        return self.name
```

#### マイグレーション

モデルで定義した情報をベースにDBを作成します

```
$ python manage.py makemigrations
$ python manage.py migrate
```

makemigrations コマンドでmigrateの為のファイルを作成します。

migrate コマンドは INSTALLED_APPS の設定を参照するとともに、 mysite/settings.py ファイルのデータベース設定に従って必要なすべてのデータベースのテーブルを作成します。

### GraphQLの為の設定

ここまでは、Djangoを使った環境の下準備でしたが、
ここからはgrapheneを使ってGraphQLの為の設定をしていきます。

#### スキーマの設定

mountainでIDに基づいて取得
all_mountains で全件取得するように設定

```
# myproject/myapplication/schema.py

import graphene
from graphene_django.types import DjangoObjectType
from myapplication.models import Mountains


class MountainsType(DjangoObjectType):
    class Meta:
        model = Mountains


class Query:
    mountain = graphene.Field(MountainsType, id=graphene.Int())
    all_mountains = graphene.List(MountainsType)

    def resolve_mountain(self, info, **kwargs):
        id = kwargs.get('id')

        if id is not None:
            return Mountains.objects.get(pk=id)
        return None

    def resolve_all_mountains(self, info, **kwargs):
        return Mountains.objects.all()
```

```
# myproject/myproject/schema.py

import graphene
import myapplication.schema


class Query(myapplication.schema.Query, graphene.ObjectType):
    pass


schema = graphene.Schema(query=Query)
```

#### エンドポイントの設定

```
# myproject/myproject/urls.py

from django.conf.urls import include, url
from django.contrib import admin
from graphene_django.views import GraphQLView
from myproject.schema import schema

urlpatterns = [
    url(r'^graphql/', GraphQLView.as_view(graphiql=True, schema=schema)),  # エンドポイント
    url(r'^admin/', admin.site.urls),
]
```

#### サンプルデータの準備

```
# myproject/myapplication/fixtures/sample.json
[
  {
    "model": "myapplication.Mountains",
    "pk": 1,
    "fields": {
      "name": "富士山",
      "height": 3776,
      "lat": 35.361111,
      "lon": 138.727778
    }
  },
  {
    "model": "myapplication.Mountains",
    "pk": 2,
    "fields": {
      "name": "北岳",
      "height": 3193,
      "lat": 35.674722,
      "lon": 138.239166
    }
  },
  {
    "model": "myapplication.Mountains",
    "pk": 3,
    "fields": {
      "name": "奥穂高岳",
      "height": 3190,
      "lat": 36.289444,
      "lon": 137.648333
    }
  }
]
```

次のコマンドでDBへ値を読み込まさせます

```
python manage.py loaddata sample
```

### 起動

起動が成功したら、http://127.0.0.1:8000/graphql/

にアクセスしましょう

Graphiqlのページにアクセスできればひとまず成功です！
続いて、値の取得ができるか確認してみましょう。

左側の領域に下記のクエリを書いて実行します

```
query {
    mountain(id:1){ 
    id
    name
    height
    lat
    lon
  }
}
```

下記のようなデータが取得できれば環境構築は成功です！

```
{
  "data": {
    "mountain": {
      "id": "1",
      "name": "富士山",
      "height": 3776,
      "lat": 35.361111,
      "lon": 138.727778
    }
  }
}
```

### 応用

ここからは、自分なりに試行錯誤しながら叩いたり、モデルを改修したりするとよいと思います

```
# 全データ取得する例
query {
    allMountains{ 
    id
    name
  }
}
```

データの取得は、query。
登録、更新、削除は、mutationが担うのですが、長くなりそうなので別記事でまとめる予定です。