【Django】006. データベース0歩目

前回はDjangoのセッションとミドルウェアについて見ていきました。

[前回記事：【Django】005. セッションとミドルウェア](https://qiita.com/ys_dirard/items/e42f329f00064d2a114c)

今回はDjangoでのデータベース操作について基本的なことを見ていきます。

今回も以下の本を参考にしています。

https://www.shuwasystem.co.jp/book/9784798062419.html


## データベースって？
膨大なデータを大勢で処理/アクセスする際に以下のようなことができて便利：
* 高速なデータアクセス
* 高度な検索
* 膨大なデータを管理
* 同時アクセス可能

データベース自体の細かいことは以下の記事等を参照

https://www.oracle.com/jp/database/what-is-database/

### よく使われるもの
|name|detail|
|-|-|
|MySQL|Djangoに限らず最も使われていそうなDB。|
|PostgreSQL|これも良く聞く、日本でも人気なDB。|
|SQLite|サーバー方式ではなくエンジン方式のデータベースに直接アクセスするタイプのDB、小さくスマホの内部でも使われているらしい。|

今回はSQLiteを使ってみます。


## データベースの設定

プロジェクトフォルダの```settings.py```にある```DATABASES```という変数に設定があります。

```python:settings.py
# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": BASE_DIR / "db.sqlite3",
    }
}
```

デフォルト ("default") ではSQLiteが指定されており、SQLiteを使うための設定がされています。

"default"以外の設定も好きに追加して、開発時はAを使い本番ではBを使うみたいなこともできるようです。

### SQLite用の設定
以下の2つを用意すればよい
|naem|detail|
|-|-|
|ENGINE|データベースへのアクセスに使われるプログラム。<br>django.db.backends.sqlite3を使う。|
|NAME|利用するデータベースの名前。SQLiteの場合はデータベースファイルのパスを設定。<br>標準：BASE_DIR / 'db.sqlite3'<br>BASE_DIRはプロジェクトのフォルダのパスが設定された変数。|

### <参考>SQLite以外のデータベースを使用する場合

#### MySQL
```python
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': <データベース名>,
        'USER': <ユーザー名>,
        'PASSWORD': <パスワード>,
        'HOST': <ホスト名>,
        'PORT': 3306, # 通常は3306で固定
    }
}

```

#### PostgreSQL
```python
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': <データベース名>,
        'USER': <ユーザー名>,
        'PASSWORD': <パスワード>,
        'HOST': <ホスト名>,
        'PORT': 5432, # 通常は5432が基本
    }
}

```

## モデルの作成

データベース(SQLite)自体の設定は終わったので、実際にテーブルを準備しようと思います。

Djangoではデータベースのテーブルの定義＝モデル (MTVのM) の定義となります。
※細かいことを言えば違うかもしれませんがざっくりそんな理解です。

モデルはプロジェクトの各アプリケーションごとのmodels.pyに用意されています (or 追加します)。

デフォルトのmodels.pyは以下のようになっているかと思います。(モデルは追加してね！と書いてある)

```python:models.py
from django.db import models

# Create your models here.

```

今回は以下の要素を持つ友達の情報を管理するテーブルを作成してみます。

|name|detail|
|-|-|
|名前|テキストの値|
|メールアドレス|テキストの値|
|性別|性別を表す真偽値。<br>True：男 / False: 女 とします。|
|年齢|整数値|
|誕生日|誕生年月日。日付の値|

モデルクラスは以下のように作成します。
```python
class モデル名(models.Model):
    変数 = フィールドのインスタンス
    ...(必要な変数分記載する)...
```

実際に作成すると以下になります。

```python:models.py
from django.db import models

class Friend(models.Model):
    name = models.CharField(max_length=100)
    mail = models.EmailField(max_length=200)
    age = models.IntegerField(default=0)
    birthday = models.DateField()
    
    def __str__(self):
        return '<Friend:id=' + str(self.id) + ', ' + \
            self.name + '(' + str(self.age) + ')>'

```

※formで登場したforms.CharFirldと今回のmodels.CharFieldは同じCharFieldですが別のクラス。

Djangoのモデルでは自動でidという属性も定義されます。

また、```__str__```とはテキストを返す特殊メソッドでオブジェクトにstrやprintを適用した場合に呼び出されます。
戻り値はstringでなければいけません。
今回はid、name、ageを出力するようにしています。

## マイグレーション
モデルの準備ができたので次はマイグレーションを行います。

マイグレーションとはデータベースの意向を行うための機能です。

あるデータベースから別のデータベースに移行するとき、必要なテーブルを作成したりしてスムーズに移行できるようにするのがマイグレーションです。

マイグレーションは他のデータベースへの移行だけでなく、プロジェクトでデータベースをアップデートするのにも使われます。

今回のようなデータベースに何もない状態からモデルをもとに必要なテーブルを作成するという際にも使われます。

以下ターミナルでマイグレーションを実行していきます。

実行は
「マイグレーションファイルの作成 → マイグレーションの実行」
と2段階で行います。

### マイグレーションファイルの作成

マイグレーションファイルは以下のように作成可能です。
```sh
$ python manage.py makemigrations アプリ名
```

今回はhelloというアプリを作成し以下としました。
```sh
$ python manage.py makemigrations hello

# log
# Migrations for 'hello':
#   hello\migrations\0001_initial.py
#     - Create model Friend
```

```hello\migrations\0001_initial.py```にマイグレーションファイルが作成されました。

```Friend```モデルが作成されたことが確認できます。

#### マイグレーションの中身
```python:0001_initial.py
# Generated by Django 5.0.7 on 2024-07-30 06:24

from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = []

    operations = [
        migrations.CreateModel(
            name="Friend",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("name", models.CharField(max_length=100)),
                ("mail", models.EmailField(max_length=200)),
                ("age", models.IntegerField(default=0)),
                ("birthday", models.DateField()),
            ],
        ),
    ]

```

```Migration```クラスが用意されています。
中に```operations```という変数で実行する処理の内容がまとめられています。
ここでは```CreateModel```なので新しいモデルをもとにテーブルを作成してね！ということですね。

マイグレーションファイルは自動で作られて、手を加えずに後段のマイグレーションの実行を行うので内容を理解しておく必要はないです。(理解しておく方が良いのは言うまでもないですが…)

### マイグレーションの実行

以下のコマンドで実行します。
```sh
$ python manage.py migrate

# log
# Operations to perform:
#   Apply all migrations: admin, auth, contenttypes, hello, sessions
# Running migrations:
#   Applying hello.0001_initial... OK
```
これだけ。

これでモデルの準備は一通り完了したので次回は実際にモデルを使ってみます。