Djangoを使って将棋棋譜管理アプリを作る2　～データベースの設定～

## はじめに
Djangoを使って将棋の棋譜管理アプリを作っていくなかでの備忘録、**第2回**です。

## 作業環境
今回の作業環境は以下の通りです

- Windows 10 Pro
- Anaconda
    - version1.7.2
    - python 3.7
        - django 2.2.5
- git
    - version 2.25.0.windows.1
- mysql
    - ver 8.0.15 for Win64 on x86_64

また、Djangoのディレクトリ構造は次のようになります。

```
- kifu_app_project/
    - kifu_app_project/
        - __init__.py
        - setting.py
        - urls.py
        - wsgi.py
    - kifu_app/
        - migrations/
        - __init__.py
        - admin.py
        - apps.py
        - models.py
        - tests.py
        - views.py
    - manage.py
    - .gitignore
```

## 本稿の内容
- データベースの設定

## データベースの設定
### settings.pyの編集
[公式ドキュメント][1]が分かりやすいので、これを見て編集するのが一番いいと思います。
内側のkifu_app_project内にsettings.pyがあるので、これを編集します。
デフォルトでは`sqlite3`に接続するようになっているので、これを`mysql`に接続するように変更します。

```python:settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'データベース名',
        'USER': 'ユーザー名',
        'PASSWORD': 'パスワード',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}
```

### MySQLライブラリのインストール
次に以下のコマンドを入力しますが、、、

```
$ python manage.py migrate
ModuleNotFound Error : No module named 'MySQLdb'
```

というエラーが出てきてしまいます。

そこで検索してみると、PyMySQLをインストールすれば解決するとあったので、実行してみますが、今度は

```
$ python manage.py migrate
mysqlclient 1.3.13 or newer is required;
```

というエラーが出てきてしまいました。

そしてこのエラーについて調べてみると、以下のようなブログを見つけました。
[Django: エラー解決法 “raise ImproperlyConfigured(‘mysqlclient 1.3.13 or newer is required; 〜) django.core.exceptions.ImproperlyConfigured: 〜”][2]

どうも、
> Django側の推奨MySQL (MariaDB)ライブラリはPyMySQLではなくmysqlclient

であるらしいです。
そこで、mysqlclientをpipでインストールします。

```
$ pip install mysqlclient
```
そして再びmigrateを実行すると。

```
$ python manage.py migrate
Apply all migrations: admin ~
```
となり、うまくいきました！

## Modelの作成
### 今回のテーブル設計
Modelとは、僕はテーブルの設計書・雛形のように捉えています。
今回は以下のテーブルを作成します。

- Informationテーブル
    - 対局情報を入れる
- LargeClassテーブル
    - 戦型の大分類を入れる
- MiddleClassテーブル
    - 戦型の中分類を入れる
- SmallClassテーブル
    - 戦型の小分類を入れる
- Kifuテーブル
    - 実際に打った手を入れる

### models.pyの編集
まずはInformationテーブルを作成します。

```python:models.py
class Information(models.Model):
    date = models.DateTimeField()
    sente = models.CharField(max_length=50)
    gote = models.CharField(max_length=50)
    result = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(3)])   # `validatos`でバリデーション(0以上3未満)
    my_result = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(3)])
    small_class = models.ForeignKey(SmallClass, on_delete=models.CASCADE)   # リレーションを定義
    create_at = models.DateTimeField(auto_now_add=True)     # 時刻を自動追加
    update_at = models.DateTimeField(auto_now=True)         # 時刻を自動更新
```
(所々日本語変数がありますが、無視してください)

使用できるFieldについては、以下のページを参考にしました。
[Django データベース モデルのフィールド 一覧表によるまとめ][3]

特にDjangoの便利だなぁと思う所は、テーブル同士のリレーションをかなり簡単につけられることではないでしょうか。
`ForeignKey(to, on_delete, **options)`で、多対1関係(toにどのモデルに関係するか)を設定できます。
これにより、後日行うクエリの取得などで、関係するデータの取得が容易になります。

同様に、他のテーブルについても、定義を行います。

```python:models.py

class LargeClass(models.Model):
    name = models.CharField(max_length=10)

class MiddleClass(models.Model):
    large_class = models.ForeignKey(LargeClass, on_delete=models.CASCADE)
    name = models.CharField(max_length=10)

class SmallClass(models.Model):
    middle_class = models.ForeignKey(MiddleClass, on_delete=models.CASCADE)
    name = models.CharField(max_length=10)

class Information(models.Model):
    # ～中略～

class Kifu(models.Model):
    information = models.ForeignKey(Information, on_delete=models.CASCADE)
    number = models.IntegerField(validators=[MinValueValidator(0)])
    te = models.CharField(max_length=20)
```

リレーション(ForeignKey)の関係により、この順番に記述しないとエラーが起こると思います。

### migrationの実行
models.pyの編集が終わったら、以下のコマンドを実行して、実際にmigrationを行ってみましょう。
migrationとは、Modelに基づいて、SQL文を実行し、テーブルの作成などを行うことです。

```
$ python manage.py makemigrations <アプリ名>
Migrations for '~'
  ~\migrations\0001_initial.py
    - Create model ~
      ... ～中略～
```
ここはプロジェクト名ではなく、アプリ名であることに注意してください。
うまくいけば、`Create model <テーブル名>`という文が表示されてきます。
また、`kifu_app_project\kifu_app\migrations`配下に、0001_initial.pyというファイルが作成されていると思います。
このファイルは、作成したModelに基づいて、テーブルとカラムの定義を行ったものです。

### 再び、migrateの実行
先程作成したMigrationファイルに基づいて、Migrateを行い、実際にテーブルを作成しましょう。

```
$ python manage.py migrate
Applying kifu_app.0001_initial... OK
```
"OK"と出れば成功です！

あとは実際にmysqlにログインして、テーブルが出来ているか確認しましょう！


## 次回予告
[Djangoデフォルトの管理サイトの設定][4]



[1]:https://docs.djangoproject.com/ja/2.2/intro/tutorial02/
[2]:https://yukun.info/django-mysqlclient-error/
[3]:https://opendata-web.site/blog/entry/14/
[4]:https://qiita.com/r-programming/items/223709d228f919dba6fc