🫠

[Python]DjangoのMigrationを最初から試してみる

に公開

以下の記事も参考になるかと思います。
https://zenn.dev/kazu1/articles/4e70817baa7dfb

個人的にバックエンドをDjangoを用いておりそれをRenderにデプロイした後にDjangoとPostgreDBの連携周りの理解がいまいちわからなくなりました。

そのためそもそもMigrationについて基礎から学び直そうと思い記事にして書くことにしました。

実際に最初から試してみる

準備

まず適当にフォルダを作成

mkdir django_migrate_practice
cd django_migrate_practice

仮想環境の準備と有効化を行う。

python -m venv venv

# 仮想環境を有効化
# Windows
venv\Scripts\activate
# mac/Linux
source venv/bin/activate

そして以下のドライバをインストールします。

pip install django psycopg2-binary

これはdjangoPostgreSQLとの連携するためのライブラリをインストールしています。
※本番環境ではpsycopg2 をインストールして使うのが良いらしい。

そしてDjangoのプロジェクトを作成します。

django-admin startproject config .

練習用のPostgreのDBを作成

ローカルのPostgreに以下のSQLを実行してpractice_dbというデータベースに
practice_userというユーザーとパスワードを設定して
このデータベースの権限をこのユーザーに与えてみます。

-- psqlでログイン後に実行
CREATE DATABASE practice_db;
CREATE USER practice_user WITH PASSWORD 'password123';
GRANT ALL PRIVILEGES ON DATABASE practice_db TO practice_user;

これで新しい練習用のデータベースを作成し、あわせてそのデータベースに接続するためのユーザーアカウントを作れました。

そしてsettings.pyにデータベース情報を追記します。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'practice_db',
        'USER': 'practice_user',
        'PASSWORD': 'password123',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

ほなmigrateしてみる

改めてmigrateって何をしているんだってばよ
というのを定義すると
migrate
= 「マイグレーションファイルに書かれたDB変更内容を、実際にPostgreSQLに反映する処理」
となります。

今の最初の段階でmigrateをしてみると、models.pyもmakemigrationsのファイルもないですが代わりに、Djangoの基本機能が使えるようになるテーブルが作られるはずです。

実際にやってみましょう!

python manage.py migrate

最初はこんなエラーがでました。

psycopg2.errors.InsufficientPrivilege: スキーマ public へのアクセスが拒否されました

その場合は以下のようにデータベースのユーザーのpractice_userに対してスキーマpublicに対して
のアクセス権限を与えてみます。

-- publicスキーマを使えるようにする
GRANT USAGE ON SCHEMA public TO practice_user;

-- publicスキーマにテーブルを作れるようにする
GRANT CREATE ON SCHEMA public TO practice_user;

-- publicスキーマに既存のテーブルがある場合、その利用権限も付与
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO practice_user;

そうしてもう一度migrateの挑戦すると..

python manage.py migrate

できました。

Postgreに新しいテーブル群ができています!

models.pyが変更された場合のmigrateを試してみる

では実際にmodels.pyが変更された時、つまり新しいテーブルを作成するときデータベースの設計を変える必要が出た時、どのようにmigrateができるか試してみましょう。
以下のイメージです。

以下を実行します。

python manage.py startapp books

これでDjangoにおけるアプリ=特定の機能を実装した小さな部品ができました。
そこでmodels.pyも自動で作成されます。

そこのmodels.pyに以下のclassを追加してみます。

class Book(models.Model):
    title = models.CharField(max_length=200)
    published_date = models.DateField()

これでtitleとpublished_dateというカラムを持つBookというテーブルが定義されます。

それではこれで今のDBのテーブルに新しく追加するテーブル定義が用意できたので、makemigrationsをしてみます。

python manage.py makemigrations books

すると自分の場合このようなエラーが出ました😅

No installed app with label 'books'.

データベースの設定情報も記載していたSettings.pyの方の、INSTALLED_APPSリストのところに今回作成したアプリのbooksを追加する必要があるようです!

よし、これで今度こそできるはず!
もう一度以下を実行すると..

python manage.py makemigrations books

できました!以下のような表示がでてきてmigrationsフォルダに自動で格納されます。

書き込まれた内容は以下です。

class Migration(migrations.Migration):
    initial = True
    dependencies = []
    operations = [
        migrations.CreateModel(
            name="Book",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("title", models.CharField(max_length=200)),
                ("published_date", models.DateField()),
            ],
        ),
    ]

そしてこの内容をDjangoがSQL文に変換してPostgreのデータベースに反映させるわけです。

ということで次に以下を実行してみます。

python manage.py migrate

そうすると、、Postgreのデータベースに新しいテーブルが作成されました!

まとめ

いかがだったでしょうか。
書いてる自分はとても勉強になりました。
DjangoがPythonコードを読み取り → SQLに変換 → PostgreSQLに反映
このような流れが起きていることを実際に手を動かすことで理解できました。

Discussion