はじめに
既存のModelに外部キー(Foreign Key)を追加しmigrationしてDBに反映させる手順と、起きやすいエラー・その対処法についてご紹介します。
1. 既存のModelに外部キーを追加
Studentモデルに外部キーを追加し、test appのClassモデルと紐付けて、生徒をクラス単位で管理できるようにする想定で書いていきます。
models.py
from django.db import models
from test.models import Class
class Student(models.Model):
# Foreign Key追加
class_id = models.ForeignKey(Class, models.DO_NOTHING)
2. Makemigrationsする
$ python manage.py makemigrations
このとき、次のような質問が表示されることがあります。
You are trying to add a non-nullable field 'class_id' to student without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
これは、「class_idフィールドには何らかの値を入れる必要があるよ〜」という意味です。
この場合、次の2つの対処方法があります。
1つ目は、フィールドにdefault=1を追加する方法です。追加したら、再度makemigrationsをします。
models.py
class Student(models.Model):
class_id = models.ForeignKey(Class, models.DO_NOTHING, default=1)
2つ目は、上記の質問が表示された時に「1」を選択し、デフォルト値として「1」を入力する方法があります。
Select an option: 1
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
Type 'exit' to exit this prompt
>>> 1
Migrations for 'student':
student\migrations\0010_student_class.py
- Add field class_id to student
3. migrateする
migrateしてDBに変更を反映します。
$ python manage.py migrate
ここで、紐付け先のテーブル(この記事ではClassテーブル)に先ほど設定した id=1 のデータが無いと、次のようなエラーが出ます。
psycopg2.errors.ForeignKeyViolation: テーブル"student_student"への挿入、更新は外部キー制約"student_student_class_id_dbc8139b_fk_class_id"に違反しています
DETAIL: テーブル"class"にキー(class_id)=(1)がありません
この場合は直接テーブルに、idカラムに1のデータを追加してあげるとmigrateが通ります。