概要
Djangoにて、マイグレーションファイルでテーブルを作成すると同時に、初期データも挿入したい場合がありますよね。外部キー制約を使っていてnull
が許容されていないケースなど。
今回、マイグレーションファイルとfixtures
を利用して実装できたので、その手順を紹介します。
手順
以下のようなモデルがあるとします。
from django.db import models
class Author(models.Model):
author_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255, null=True)
class Meta:
db_table = 'author'
class Book(models.Model):
book_id = models.AutoField(primary_key=True)
title = models.CharField(max_length=255, null=True)
# author_id = models.ForeignKey('Author', on_delete=models.CASCADE, null=False, db_column='author_id')
class Meta:
db_table = 'book'
ここで、Book
モデルのauthor_id
は外部キー制約を利用しており、null=False
です。このままコメントアウトを外して実行すると、author
テーブルにまだレコードがないので外部キー制約違反でエラーになってしまいます。
ということで、以下の順序で実施します。
①author
テーブルとbook
テーブル(author_id
なし)の作成を行うマイグレーション生成
②初期データ用のJSONを作成
③author
テーブルにレコードを追加するマイグレーション生成
④book
テーブルにauthor_id
(外部キー)を追加するマイグレーション生成
⑤マイグレート実施
①author
テーブルとbook
テーブル(author_id
なし)の作成を行うマイグレーション生成
上記のmodels.py
で一度python manage.py makemigrations
を実施してマイグレーションファイルを作成。
1つ目であれば0001_initial
と言う名前になります。
②初期データ用のJSONを作成
次に挿入データ用のJSONを作成し、fixtures
ディレクトリ以下におきます。
[
{
"model": "app_name.author",
"pk": 1,
"fields": {
"name": "Taro Yamada"
}
},
{
"model": "app_name.author",
"pk": 2,
"fields": {
"name": "Jiro Tanaka"
}
}
]
③author
テーブルにレコードを追加するマイグレーション生成
0002_load_author_data.py
と言うファイルをmigrations
ディレクトリ以下に作成して、以下の内容を書きます。ここでは、先ほど作成したfixtures
を実行するコマンドを書いています。
from django.core.management import call_command
from django.db import migrations
def load_fixture(apps, schema_editor):
call_command('loaddata', 'fixtures/author_initial_data.json', app_label='book')
class Migration(migrations.Migration):
dependencies = [
('book', '0001_initial'),
]
operations = [
migrations.RunPython(load_fixture),
]
上記ではcall_command
関数を使用して、Djangoのloaddata
コマンドを呼び出しています。
loaddata
コマンドは、指定されたJSONファイルからデータを読み込み、DBに挿入してくれます。
④book
テーブルにauthor_id
(外部キー)を追加するマイグレーション生成
最後に、Bookモデルの外部キーのコメントアウト(author_id...
)を外し、再びpython manage.py makemigrations
を実施してマイグレーションファイルを作成します。
from django.db import models
class Author(models.Model):
author_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255, null=True)
class Meta:
db_table = 'author'
class Book(models.Model):
book_id = models.AutoField(primary_key=True)
title = models.CharField(max_length=255, null=True)
author_id = models.ForeignKey('Author', on_delete=models.CASCADE, null=False, db_column='author_id') # コメントアウトを外しました
class Meta:
db_table = 'book'
これで、0003
から始まるマイグレーションファイルが作成されるはずです。
⑤マイグレート実施
これで合計3つのマイグレーションファイルの準備ができましたので、
以下のコマンドですべてのマイグレーションを実行します。
python manage.py migrate
無事に、外部キー制約がある状態でテーブルが作成され、レコードも挿入されていればOKです。
参考・その他
以下の記事を参考させていただきました。
また、マイグレーションファイル内で直接SQLスクリプトを実行してデータを挿入する方法もあると思います。個人的には「fixtures
ディレクトリさえ見れば挿入した(初期)データがわかる」という点からfixtures
の方がわかりやすいかなと感じています。