ブログBLOG

\ Web・ゲーム開発に関する情報を発信中 /

【超簡単】Djangoのmigrate実行時に初期データをデータベースへ自動追加する方法

Django
django , python
20250724_django-migrate-auto-data-insert-tmb

ご覧いただきありがとうございます!
領護(りょうご)です。

マスタデータやテストデータを開発開始時に追加しておきたいことってありませんか?
この記事では、post_migrateシグナルを使用して、migrateコマンド実行時に初期データをデータベースへ自動追加する方法を解説します。
とても簡単に実装できるので是非試してみてください!

目次

実行環境

今回の解説で使用する環境は以下の通りです。

Docker Desktop:4.43.2
Python:3.13.5
Django:5.2.4
Sqlite3

ディレクトリ構成

sample_web/
├── .env                  # 環境変数ファイル
├── db.sqlite3            # SQLiteデータベースファイル
├── docker-compose.yml    # Docker Compose設定ファイル
├── Dockerfile            # Dockerイメージ定義ファイル
├── manage.py             # Django管理スクリプト
├── requirements.txt      # プロジェクトの依存ライブラリ一覧
│
├─home                    # Djangoアプリケーションフォルダ
│   ├── admin.py          # 管理サイト設定ファイル
│   ├── apps.py           # アプリケーション設定ファイル
│   ├── management.py     # カスタム管理コマンドやシグナルハンドラなどを配置
│   ├── models.py         # データベースモデル定義ファイル
│   ├── tests.py          # テストファイル
│   ├── urls.py           # アプリケーションのURLルーティング
│   ├── views.py          # ビュー関数/クラス定義ファイル
│   └── __init__.py       # Pythonパッケージとして認識させるためのファイル
│   └─migrations          # データベーススキーマ変更履歴(マイグレーションファイル)
│       ├── 0001_initial.py # 初期マイグレーションファイル
│       └── __init__.py     # Pythonパッケージとして認識させるためのファイル
│
└─sample_project          # Djangoプロジェクトのメイン設定フォルダ
    ├── asgi.py           # ASGI互換Webサーバーエントリーポイント
    ├── settings.py       # プロジェクトの主要設定ファイル
    ├── urls.py           # プロジェクト全体のURLルーティング
    ├── wsgi.py           # WSGI互換Webサーバーエントリーポイント
    └── __init__.py       # Pythonパッケージとして認識させるためのファイル

今回の解説では、上記のディレクトリ構成を使用します。
主に扱うファイルは、home/admin.py、home/apps.py、home/management.py、home/models.pyの4つです。

モデルを定義する

例として使用するモデルをhome/models.pyに作成します。
今回は、ゲームカテゴリーを管理するモデルを作成してみます。

models.py
from django.db import models


# ゲームカテゴリー管理モデル
class Category(models.Model):

    # ID(手動入力)
    id = models.PositiveIntegerField(primary_key=True, unique=True, verbose_name="ID")

    # ゲームカテゴリー名
    name = models.CharField(max_length=50, unique=True, verbose_name="ゲームカテゴリー名")

    class Meta:
        verbose_name = "ゲームカテゴリー"
        verbose_name_plural = "ゲームカテゴリー"
        ordering = ["id"]

    def __str__(self):
        return f"{self.id}: {self.name}"

ID(手動入力)とゲームカテゴリー名の2つのフィールドを作成します。
通常、DjangoのIDフィールドはAutoFieldで自動的に連番が振られます。
今回は、挙動を分かりやすくするため、あえてPositiveIntegerFieldを使用して手動入力にしています。

データを自動追加するコードを作成

次に、データベースに初期データを追加するコードをhome/management.pyに作成します。
management.pyファイルは新規作成してください。

management.py
from .models import Category

# マイグレーション完了後に初期カテゴリーデータを追加するハンドラ
def create_initial_data(sender, **kwargs):

    # 追加したい初期データ
    initial_categories_data = [
        {"id": 1, "name": "アクション"},
        {"id": 2, "name": "RPG"},
        {"id": 3, "name": "アドベンチャー"},
        {"id": 4, "name": "シミュレーション"},
        {"id": 5, "name": "ストラテジー"},
        {"id": 6, "name": "パズル"},
        {"id": 7, "name": "スポーツ"},
        {"id": 8, "name": "レース"},
        {"id": 9, "name": "ホラー"},
        {"id": 10, "name": "音楽"},
    ]

    # 作成数カウント
    created_count = 0

    # データをDBに追加
    for category_data in initial_categories_data:

        # idとnameが一致すれば既存とみなし、なければ新規作成またはID衝突エラー
        category, created = Category.objects.get_or_create(
            id=category_data["id"], name=category_data["name"]
        )

        # 新規作成した場合はカウントを加算
        if created:
            created_count += 1

    print(f"--- 初期カテゴリーデータの追加が完了しました ({created_count}件追加) ---")

データベースに初期データを追加するコードです。
重要部分を詳しく解説しますね。

management.py
# 追加したい初期データ
initial_categories_data = [
    {"id": 1, "name": "アクション"},
    {"id": 2, "name": "RPG"},
    {"id": 3, "name": "アドベンチャー"},
    {"id": 4, "name": "シミュレーション"},
    {"id": 5, "name": "ストラテジー"},
    {"id": 6, "name": "パズル"},
    {"id": 7, "name": "スポーツ"},
    {"id": 8, "name": "レース"},
    {"id": 9, "name": "ホラー"},
    {"id": 10, "name": "音楽"},
]

データベースに追加したい初期データを配列(リスト)と辞書を使って定義しています。
この形式は視認性が高く、管理しやすいのでおすすめです。

20250724_django-migrate-auto-data-insert-01

上記のゲームカテゴリーをデータベースに10レコード追加します。

management.py
# 作成数カウント
created_count = 0

# データをDBに追加
for category_data in initial_categories_data:

    # idとnameが一致すれば既存とみなし、なければ新規作成またはID衝突エラー
    category, created = Category.objects.get_or_create(
        id=category_data["id"], name=category_data["name"]
    )

    # 新規作成した場合はカウントを加算
    if created:
        created_count += 1

Djangoのメソッドであるget_or_create()を使用して初期データを追加します。

指定したidとnameが完全に一致するデータがデータベースに存在する場合、その既存のデータを取得します。
もし一致するデータがなければ、新しいデータを新規作成してデータベースに追加します。

これにより、migrateコマンドを何度実行しても、同じデータが重複して追加されることを防いでいます。

「created_count」は、実際に新規作成されたデータの数をカウントしています。
最後にその結果を出力することで、正しくデータが追加されたか確認できます。

migrate実行時にコードを実行する

migrateコマンド実行時に、先ほど作成したコードが自動で実行されるように設定します。
初期データを追加したいアプリケーションのapps.pyファイル(今回の例ではhome/apps.py)にコードを追加します。

apps.py
from django.apps import AppConfig
from django.db.models.signals import post_migrate


class HomeConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "home"

    # migrateコマンド実行時、ゲームカテゴリーデータをDBに追加
    def ready(self):
        from .management import create_initial_data

        post_migrate.connect(create_initial_data, sender=self)

migrateコマンド実行時に、先ほど作成したコードを発火させるためのコードです。
重要部分を詳しく解説しますね。

apps.py
    # migrateコマンド実行時、ゲームカテゴリーデータをDBに追加
    def ready(self):
        from .management import create_initial_data

        post_migrate.connect(create_initial_data, sender=self)

Djangoアプリケーションがロードされる準備ができた時に呼び出されるメソッドのready()を使用して、post_migrate()を実行しています。
post_migrate()が実行されると、先ほど作成した初期データをデータベースに追加する関数であるcreate_initial_data()を実行するように登録しています。
このように設定しておくことで、アプリのマイグレーション完了時にのみ初期データが自動で追加されます。

Django管理画面に表示する

データが正しく追加されたかを確認するため、Djangoの管理画面にCategoryモデルを表示するように設定します。
home/admin.pyに以下のコードを作成します。

admin.py
from django.contrib import admin
from .models import Category


# Categoryモデルの管理サイトでの表示設定
class CategoryAdmin(admin.ModelAdmin):

    # 一覧画面に表示するフィールド
    list_display = ("id", "name")

    # 検索ボックスの対象とするフィールド
    search_fields = ("name",)

    # デフォルトの並び順
    ordering = ("id",)


admin.site.register(Category, CategoryAdmin)

Djangoの管理画面にCategoryモデルを表示するコードです。
idとnameが表示されるように設定しました。
これで準備完了です!

migrationsとmigrateを実行する

データベースにモデルの変更を反映し、同時に初期データを追加します。

python manage.py makemigrations
python manage.py migrate

ターミナルで「makemigrations」「migrate」コマンドを実行してDBに反映させます。

初期データが追加されたか動作確認

20250724_django-migrate-auto-data-insert-02

Django管理画面の「HOME」アプリの下に「ゲームカテゴリー」という項目が追加され、クリックするとmigrate実行時に追加された10個のゲームカテゴリーデータが表示されています。
これでmigrateコマンド実行時に、データベースへ初期データを自動追加することができました!

最後に

今回は、Djangoのmigrateコマンド実行時に、データベースへ初期データを自動追加する方法を解説しました。
開発環境で必須となるマスタデータや、テスト用のダミーデータを投入する際に非常に役立ちます。
ぜひ使ってみてください!


\ よかったらシェアしてね /

関連記事