[Django] makemigrationsとmigrateについてわかってきたのでまとめてみた

## はじめに
Djangoを使っていて気になることがありませんか、、？
`models.py`に編集を加えた後、`makemigrations`や`migrate`を実行しませんでしたか？
僕がはじめてDjangoを触った時は、脳死でこのコマンドを実行していました。

webアプリ開発でDjangoを使うようになってから半年ほどたち、このコマンドが何をしているのか、
少しずつ理解できてきたので、備忘録として記事に残したいと思います。

### この記事が参考になりそうな人
- 最近Djangoを使い始めて、慣れてきた人
- `makemigrations`や`migrate`について理解したい人

## 前知識
###マイグレーションについて

- [Django公式ドキュメント](https://docs.djangoproject.com/en/3.1/topics/migrations/#module-django.db.migrations)では以下のように説明されています
> Migrations are Django’s way of propagating changes you make to your models (adding a field, deleting a model, etc.) into your database schema. They’re designed to be mostly automatic, but you’ll need to know when to make migrations, when to run them, and the common problems you might run into.

- [DeepL](https://www.deepl.com/ja/translator)での翻訳
>移行とは、モデルに加えた変更 (フィールドの追加やモデルの削除など) をデータベーススキーマに反映させるための Django の方法です。ほとんど自動で行われるように設計されていますが、いつ移行を行うのか、いつ実行するのか、そしてよくある問題について知っておく必要があります。


つまり、マイグレーションとは

- データベースに変更を加えるための仕組み
- `models.py`に対して行った変更をデータベーススキーマに反映させる仕組み
-  データベースのバージョン管理システムのようなもの（GitHubを使っている人はこれが一番納得しやすいかも？）

### マイグレーションファイルについて
- `models.py`を元に作られるファイル
- `models.py`の内容をデータベースに反映させるための中間ファイル
- 1番最初の`models.py`の内容と、それを基準に`models.py`の変更によってできる差分のデータファイル

## `./manage.py makemigrations`でなにが起きる？ 
結論から言うと**マイグレーションファイル**が作成されます。

`Person`モデル

```py
from django.db import models


class Person(models.Model):
    name = models.CharField(max_length=30)
    age = models.IntegerField()
```

`makemigrations`を実行すると

```terminal
$ ./ manage.py makemigrations
```

`Person`モデルを元に**マイグレーションファイル**が作成されます


```py

from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Person',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=30)),
                ('age', models.IntegerField()),
            ],
        ),
    ]

```

今、`Person`モデルに対する**マイグレーションファイル**が存在しなかったので、`0001_initial.py`というファイル名でファイルが作成されました。
以後、この`0001_initial.py`が元となり、マイグレーションファイルが更新されていきます。

では、ここで`Person`モデルに`weight`というフィールドを追加し、もう一度`makemigrations`を実行してみます

```py
from django.db import models


class Person(models.Model):
    name = models.CharField(max_length=30)
    age = models.IntegerField()
    weight = models.IntegerField()
```

```terminal
$ ./ manage.py makemigrations
```

```py
from django.db import migrations, models
import django.utils.timezone


class Migration(migrations.Migration):

    dependencies = [
        ('sample_app', '0001_initial'),
    ]

    operations = [
        migrations.AddField(
            model_name='person',
            name='weight',
            field=models.IntegerField(default=django.utils.timezone.now),
            preserve_default=False,
        ),
    ]
```
すると、`0001_init.py`に依存した、`0002_person_weight.py`が新規作成されます。
>この`0002_person_weight.py`には、`0001_init.py`との差分が記録されているイメージです。


つまり、`makemigrations`を実行すると、モデルに変更があれば、その変更をファイルに残します。
しかし、**`makemigrations`を実行しただけではデータベースには反映されません。**

## `./manage.py migrate`でなにが起きる？
`makemigrations`によってできた**マイグレーションファイル**をデータベースに反映させます。
> マイグレーションファイルに従って、データベースに変更を加えるイメージです。

`./manage.py migrate アプリ名 マイグレーション名`で特定のマイグレーションファイルを反映させることができます。
アプリ名とマイグレーション名を省略した場合は、未適用のマイグレーションファイルを全てデータベースに反映させます。
>`./manage.py migrate`
これだと未適用のマイグレーションファイルが全てデータベースに反映させます。

## さいごに
記事の内容や書き方にまだまだ改善できる点が多いと思いますが、書きながら覚えて改善していきたいと思います！

記事書いてて楽しかったので、これから定期的に投稿していこうとかな思います