10分くらい詰まりました。
ググっても解決策見つからず、もしかしたら同じような問題に悩む方もいるかもと思いメモしておきます。
前提
利用しているのは、DjangoとPostgreSQLです。
Djangoでデフォルトで作成されるauth_userテーブルを使っていましたが、auth_userテーブルを拡張した新規テーブルQiitaUserを作成して、以降はQiitaUserを利用するようにしました(テーブル名は仮)。
以前のmodels.py
from django.conf import settings
from django.db import models
class Engineers(models.Model):
name = models.CharField(max_length=1000)
user = models.ForeignKey(settings.AUTH_USER_MODEL, to_field='id', on_delete=models.CASCADE, null=True)
変更後のmodels.py
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.db import models
class Engineer(models.Model):
name = models.CharField(max_length=1000)
user = models.ForeignKey(settings.AUTH_USER_MODEL, to_field='id', on_delete=models.CASCADE, null=True)
class QiitaUser(AbstractUser):
is_owner = models.BooleanField(default=False)
settings.py
AUTH_USER_MODEL = 'QiitaUser'
上記のようにmodelsとsettings.pyを変更して、migrationを実行してqiitauserテーブルが作成されたことを確認。
元々auth_userのuser_idを参照していたengineerテーブルは、qiitauserテーブルのidを外部キーとして参照するようになった(認識でした)。
詰まったこと
QiitaUserのid指定でEngineerのデータを登録しようとすると...
db=# update engineer set user_id = 10 where id = 15;
ERROR: insert or update on table "engineer" violates foreign key constraint "engineer_user_id_xxxxxxxx_fk_auth_user_id"
DETAIL: Key (user_id)=(10) is not present in table "auth_user".
QiitaUserテーブルに存在するidをEngineerのuser_idに指定すると、auth_userテーブルにはそのidのレコードはありませんとエラーになってしまう。
QiitaUserのidを参照して欲しいのに、auth_userのidを参照してしまっています。
原因と解決策
自分の開発環境の場合は、すでにauth_userへの外部キー制約がついている状態で、新規にauth_userを拡張したテーブルを定義してAUTH_USER_MODEL=QiitaUserを参照するようにしたため、外部キー制約がauth_userとQiitaUserの両方についていて、auth_userの方を参照しようとしてエラーになってしまっていたよう。
db=# \d engineer;
Table "public.engineer"
Column | Type | Collation | Nullable | Default
------------------------+-------------------------+-----------+----------+---------------------------------------------------
id | integer | | not null | nextval('engineer_id_seq'::regclass)
name | character varying(1000) | | not null |
user_id | integer | | |
Indexes:
"engineer_pkey" PRIMARY KEY, btree (id)
"engineer_user_id_xxxxxxxx" btree (user_id)
Foreign-key constraints:
"engineer_user_id_xxxxxxxx_fk_accounts_" FOREIGN KEY (user_id) REFERENCES accounts_visualuser(id) DEFERRABLE INITIALLY DEFERRED
"engineer_user_id_xxxxxxxx_fk_auth_user_id" FOREIGN KEY (user_id) REFERENCES auth_user(id) DEFERRABLE INITIALLY DEFERRED
PostgreSQLは \d <tablename>;
でテーブル定義が確認できます。
auth_userのidを参照している外部キー制約は、不要になので削除します。
db=# ALTER TABLE engineer DROP CONSTRAINT IF EXISTS engineer_user_id_xxxxxxxx_fk_auth_user_id;
ALTER TABLE
再度、Engineerのデータを登録しようとすると...
db=# update engineer set user_id = 10 where id = 15;
UPDATE 1
無事成功しました。
auth_userを参照するEngineerを定義してmigrateすることなく、Engineerを作成して初めてmigrateするタイミングでauth_userを拡張したModelを使うようにしていれば、今回のような問題は起きなかったと思います。
すでにauth_userを使っている状態で新しくCustomUserを定義して利用する場合は注意が必要ですね〜。