Django+Reactで学ぶプログラミング基礎(6): Djangoチュートリアル(投票アプリその2)

##### [前回] [Django+Reactで学ぶプログラミング基礎(5): Djangoチュートリアル(投票アプリその1)](https://qiita.com/mingchun_zhao/items/477ea8780a88b97f309a)

## はじめに

[Django公式チュートリアル](https://docs.djangoproject.com/ja/4.0/intro/tutorial01/)、その2です。
前回は、プロジェクト、アプリ、ビューの作成まで行いました。
今回は、どのような内容になるでしょうか。

## Djangoアプリ作成(その2): 投票(poll)アプリ

### 今回の内容

- データベースはMySQLを使用
- Djangoのデータベース設定
- Djangoモデルの作成
- Djangoモデルを有効にする
- Django Admin(管理サイト)

### データベースはMySQLを使用
- Djangoは、デフォルトで`SQLite`をデータベースとして使用
    - SQLiteはPythonに標準で組み込まれている
- 本番環境では、 スケーラブルなデータベース使用が推奨される
    - 今回は、MySQLを使用
- MySQLをインストール
    - `https://dev.mysql.com/downloads/mysql/`から
        - 最新版`Windows (x86, 64-bit), ZIP Archive`をダウンロード
    - インストール手順
        - [Microsoft Windows に MySQL をインストールする](https://dev.mysql.com/doc/refman/8.0/ja/windows-installation.html)

### Djangoのデータベース設定

#### MySQL側の設定

- `%PROGRAMDATA%\MySQL\MySQL Server 8.0\my.ini`設定ファイルに文字コード設定を追記
```
[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
character-set-server = utf8mb4
skip-character-set-client-handshake
collation-server = utf8mb4_general_ci
init-connect = SET NAMES utf8mb4
```

- MySQLを再起動
- データベースを作成
```
>mysql -u root -p
mysql> CREATE DATABASE kanban;
```
- ユーザーを作成
```
mysql> CREATE USER 'kanban'@'localhost' IDENTIFIED BY 'kanban';
mysql> GRANT ALL PRIVILEGES ON kanban.* TO 'kanban'@'localhost';
```

#### Django側の設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523098/eee7947c-1b61-ab8a-f73a-33ecde0b6efb.png)

- MySQL接続設定
```pollsite/settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'kanban',
        'USER': 'kanban',
        'PASSWORD': 'xxxx',
        'HOST': '127.0.0.1',
        'PORT': '3306',
        'OPTIONS': {
            'charset': 'utf8mb4',
            'sql_mode': 'TRADITIONAL,NO_AUTO_VALUE_ON_ZERO,ONLY_FULL_GROUP_BY',
        },
    }
}
```

- 文字コードを設定
```pollsite/settings.py
LANGUAGE_CODE = 'ja'
```

- タイムゾーンを設定
```pollsite/settings.py
TIME_ZONE = 'Asia/Tokyo'
```

- Djangoインスタンスで有効化されているアプリケーションを確認(修正はしない)
```pollsite/settings.py
 # Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
```

#### 上記アプリケーションで使用するデータベースのテーブルを作成

- VS Codeターミナルで、仮想環境をアクティベート
```
C:\kanban\pollsite>..\venv\.venv\Scripts\activate
```

- `mysqlclient`をインストール
```
(venv) C:\kanban\pollsite>pip install mysqlclient
```

- `migrate`コマンドを実行
```
(venv) C:\kanban\pollsite>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
... ...
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK
```
- MySQLに接続し、テーブルを確認
```
(venv) C:\kanban\pollsite>mysql -u kanban -p kanban
mysql> show tables;
+----------------------------+
| Tables_in_kanban           |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
+----------------------------+
10 rows in set (0.00 sec)
mysql> exit
```

### Djangoモデルの作成

- モデルとは
    - データベースのレイアウトとそれに付随するメタデータ
    - Pythonクラスで表現
    - モデルのフィールドは`Field`クラスのインスタンスとして表現
- 投票アプリでは、二つのモデルを作成
    - `Question`モデル
        - `question`フィールド
        - `pub_date`フィールド
    - `Choice`モデル
        - `choice_text`フィールド
        - `votes`フィールド
    - 二つのモデルの関係
        - 各`Choice`は1つの`Question`に関連づけられる
        - `ForeignKey`を使用し、リレーションシップを定義
        - Djangoは一般的なデータベースリレーションシップすべてサポート
            - 多対一
            - 多対多
            - 一対一
```polls/models.py
from django.db import models


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
```

### Djangoモデルを有効にする

- Djangoアプリケーションは`プラガブル(pluggable)`
    - アプリケーションを他のDjangoインストールで使用可能
        - 複数プロジェクトで使ったり
        - 単体配布可能

#### 投票アプリをインストールしたことをプロジェクトに伝える
- アプリケーションをプロジェクトに含める
- 構成クラス`PollsConfig`への参照を`INSTALLED_APPS`設定に追加
```pollsite/settings.py
INSTALLED_APPS = [
    'polls.apps.PollsConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
```

#### Djangoにモデルが変更されたことを伝える
- `makemigrations`を実行
- 変更をマイグレーションの形で保存
    - マイグレーションとは、Djangoがモデル(データベーススキーマ)の変更を保存する方法
    - 実体はディスク上のファイル
```
(venv) C:\kanban\pollsite>python manage.py makemigrations polls
Migrations for 'polls':
  polls\migrations\0001_initial.py
    - Create model Question
    - Create model Choice
```

#### migrateを再度実行し、データベースでモデルのテーブルを作成
- モデルの変更とデータベーススキーマが同期される
```
(venv) C:\kanban\pollsite>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
  Applying polls.0001_initial... OK
```

#### まとめ: モデルの変更を行う3ステップガイド

- モデルを変更
    - `models.py`
- 変更保存のためマイグレーションを作成
    - `python manage.py makemigrations`を実行
- データベースに変更を適用
    - `python manage.py migrate`を実行
- ※ マイグレーションの作成と適用のコマンドが分割された理由
    - マイグレーションをバージョン管理システムにコミットし、アプリとともに配布するため
    - 自分自身の開発が容易になるだけでなく、他の開発者や本番環境にとって使いやすいものになる

### Django Admin(管理サイト)

- サイト管理者がコンテンツ追加、変更そして削除のための管理サイト
- Django管理サイトはデフォルトで有効化
- Djangoはモデル管理インタフェース群の生成を完全自動化

#### 管理ユーザーを作成
- 管理サイトにログインできるユーザーを作成
```
(venv) C:\kanban\pollsite>python manage.py createsuperuser
```

#### 開発サーバーを起動し、管理サイトにアクセス

- 開発サーバーを起動
```
(venv) C:\kanban\pollsite>python manage.py runserver
```

- ブラウザで`http://127.0.0.1:8000/admin/`にアクセスし、管理サイトにログイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523098/bce9f9a2-157d-399f-f5a9-fd2d68c08cb3.png)

#### 投票アプリを管理サイトで編集できるようにする

- `Question`オブジェクトが`admin`インタフェースを持つことを、管理サイトに伝える
```polls/admin.py
from django.contrib import admin

from .models import Question

admin.site.register(Question)
```

#### ブラウザを更新(F5)し、`Questions`を追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523098/61123a93-f111-4e8a-3e5d-5cad4038424e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523098/49b2f7c3-abe5-76de-5bc5-e4d903cf4587.png)

## おわりに

MySQLを導入し、Djangoモデルと関連付けました。
Django管理サイトで、アプリ管理も行いました。
次回も続きます。お楽しみに。

##### [次回] [Django+Reactで学ぶプログラミング基礎(7): Djangoチュートリアル(投票アプリその3)](https://qiita.com/mingchun_zhao/items/d352c9520337e86e0caa)