環境
MacOS Sequoia Version 15.3
Python 3.12.8
Django 5.1.6
エラー内容
$ python manage.py makemigrations
Traceback (most recent call last):
File "/Users/path-to-project-directory/.venv/lib/python3.12/site-packages/django/apps/config.py", line 235, in get_model
return self.models[model_name.lower()]
~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
KeyError: 'myuser'
During handling of the above exception, another exception occurred:
#(中略)
File "/Users/path-to-project-directory/.venv/lib/python3.12/site-packages/django/contrib/auth/__init__.py", line 194, in get_user_model
raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model 'issuing.MyUser' that has not been installed
※ 今回作成したカスタムユーザーモデルの名前は MyUser
です
経緯
このエラーが出た経緯は次の通りです
- 拡張性の観点から、
AbstractBaseUser
を継承したカスタムユーザーを作成したかった1 - しかし、実装の大部分は
AbstractUser
と被っている -
AbstractUser
の公式の実装をベースに、必要な部分だけ改変することにした
改変の内容は以下の通りです
- まず、
AbstractUser
とUserManager
の実装をコピペした - コピペしたコードに以下の変更を加えた
-
AbstractUser
のクラス名をMyUser
に変更 -
UserManager
のクラス名をMyUserManager
に変更 -
AbstractUser
内のobjects = UserManager()
をobjects = MyUserManager()
に変更
-
-
python manage.py makemigrasions
を実行した - すると、上記のエラーが出た
解決策
カスタムユーザークラス内の、class Meta
の部分から、abstract = True
の行を削除すると、解決しました。
django/django/contrib/auth/models.py
class AbstractUser(AbstractBaseUser, PermissionsMixin):
"""
An abstract base class implementing a fully featured User model with
admin-compliant permissions.
Username and password are required. Other fields are optional.
"""
username_validator = UnicodeUsernameValidator()
#(中略)
EMAIL_FIELD = "email"
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ["email"]
class Meta:
verbose_name = _("user")
verbose_name_plural = _("users")
abstract = True # ← この行を削除する
#(後略)
補足
Django のモデルに対して定義できる Meta
クラスは、モデルに付加情報を与えることができます2。よく用いられる項目として、以下のようなものがあります。
verbose_name
verbose_name_plural
ordering
ここで、abstract
という項目もあり、この項目を True
にすると、そのモデルは Abstract base class
になります。Abstract base class
には、以下のような特徴があり、同じ特徴を持ったモデルを複数個作成する場合に、便利な機能になっています3。
- DB にテーブルが作成されない
- 他のモデルの基底クラスとして用いると、
Abstract base class
のフィールドが継承先にも追加される
AbstractUser
は Abstract base class
のため、テーブルとして使用したければ、abstract=True
を削除する必要があったというわけでした。