Django カスタムユーザーのmigrateができない

Djangoアプリを構築する際にカスタムユーザーを作ることがあるのですが、毎回migrationができずにはまっています。
対処法をメモしておこうと思いました。
Djangoのversionは3.2.7

いつものはまるやり方

まずはいつも通りはまってみようと思います。
まずregisterというアプリにカスタムユーザーを定義します。

django-admin startproject project .
python manage.py startapp register


AbstractUserを継承します。

# register/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    pass


次にmigrationsを実行してみましょう。

python manage.py makemigrations
>>>
No changes detected


何もおきません。
だいたいここであせってmigrateします。

python manage.py migrate
>>>
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK


そうすると組み込みのユーザーモデルがmigrateされてしまいます。
焦っていなくても最初に組み込みのユーザーモデルで行っていて後から切り替えたい、ということもあります。
なので、結構あるパターンだと思います。

ここから解決をしていきましょう。

settings.pyの編集


まず、以下の2か所の追記が必要です。
結構忘れやすいポイントです。

# project/settings.py

...

INSTALLED_APPS = [
    'register.apps.RegisterConfig',  # 追加
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

...

# 追加
AUTH_USER_MODEL = 'register.User'

...


さっそくmakemigrationをしてみましょう。

python manage.py makemigrations
>>>
  register\migrations\0001_initial.py
    - Create model User


無事にmigrationファイルができました。
しかしmigrateしようとするとerrorが起きます。

python manage.py migrate

>>>
Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    main()
  File "manage.py", line 18, in main
    execute_from_command_line(sys.argv)
....
  raise InconsistentMigrationHistory(
  django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial is applied before its dependency register.0001_initial on database 'default'.


やけくそになってcreatesuperuserを作ろうとしたりしますが、失敗します。

python manage.py createsuperuser
>>>
Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    main()
  File "manage.py", line 18, in main
    execute_from_command_line(sys.argv)
...
  return Database.Cursor.execute(self, query, params)
  django.db.utils.OperationalError: no such table: register_user
  


当然ですが、register_userなんていうテーブルがないよ、と怒られているわけです。
とにかくmigrateしないと始まりません。

migrate時のエラーを注意深くみるとadminが悪さをしてることに気づきます。
adminに関する記述をコメントアウトすることでmigrateできるようになります。

# project/settings.py

INSTALLED_APPS = [
    'register.apps.RegisterConfig',  # 追加
    # コメントアウト 'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]


# project/urls.py

urlpatterns = [
    # コメントアウト path('admin/', admin.site.urls),
]


実行してみます。

python manage.py migrate
>>>
Applying register.0001_initial... OK


うまくいきました。
そうしたらコメントアウトを解除して再びmigrateしましょう。

python manage.py migrate
>>>
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, register, sessions
Running migrations:
  No migrations to apply.


これでオッケーです。

既にスーパーユーザーを作っていたら、もう一回createsuperuserをします。

その他


何もmigrateしていない状態で、settings.pyへの追記をきちんとしてから、makemigrations、migrateをすると一発でうまくいきます。

TOPページ