Django のユーザーモデルをカスタマイズする(AbstractUser の拡張)

Django 標準の User モデルは usernameemailpassword などの基本フィールドを備えていますが、実際のプロジェクトでは「電話番号を必須にしたい」「メールアドレスでログインしたい」といった要件がほぼ確実に出てきます。Django ではプロジェクト開始時にカスタムユーザーモデルを作っておくことが公式に推奨されています。

なぜカスタマイズが必要か

標準の User モデルはログイン ID が username 固定で、追加フィールドを持ちません。後からユーザーモデルを差し替えるのは既存データのマイグレーションが非常に複雑になるため、プロジェクトの初期段階で対応しておくのが鉄則です。

標準 User モデル

username でログイン。フィールドの追加や変更ができない

カスタム User モデル

ログイン ID やフィールドを自由に変更できる。プロジェクト開始時に作るのが推奨

AbstractUser を使った拡張

最もシンプルなカスタマイズ方法は AbstractUser を継承することです。標準の User モデルが持つすべてのフィールドと機能を引き継ぎながら、独自のフィールドを追加できます。

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

class User(AbstractUser):
    phone = models.CharField(max_length=20, blank=True, verbose_name='電話番号')
    bio = models.TextField(blank=True, verbose_name='自己紹介')
    date_of_birth = models.DateField(null=True, blank=True, verbose_name='生年月日')

AbstractUser を継承しているため、usernameemailpasswordfirst_namelast_nameis_activeis_staff などの標準フィールドはそのまま使えます。ここに phonebiodate_of_birth を追加しただけです。

AUTH_USER_MODEL の設定

カスタムユーザーモデルを Django に認識させるには、settings.pyAUTH_USER_MODEL を設定します。

# settings.py
AUTH_USER_MODEL = 'accounts.User'

この設定は migrate を実行する前に行う必要があります。すでにデフォルトの User モデルでマイグレーションを実行した後に変更すると、テーブルの不整合が発生します。

accounts アプリを作成する

AbstractUser を継承したモデルを定義する

AUTH_USER_MODEL を settings.py に設定する

makemigrations → migrate を実行する

他のモデルからの参照

カスタムユーザーモデルを外部キーで参照するときは、settings.AUTH_USER_MODEL を使います。from django.contrib.auth.models import User を直接インポートしてはいけません。

from django.conf import settings
from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='articles'
    )

settings.AUTH_USER_MODEL は文字列('accounts.User')を返すため、モデルの定義順序に依存せず安全に参照できます。ビューやフォームでユーザーモデルを取得する場合は get_user_model() を使います。

from django.contrib.auth import get_user_model

User = get_user_model()
users = User.objects.all()
settings.AUTH_USER_MODEL

モデル定義の ForeignKey 等で使う。文字列で参照するため循環インポートを回避できる

get_user_model()

ビューやフォームで使う。実際のモデルクラスを返す

メールアドレスでログインする

username の代わりにメールアドレスでログインさせたい場合は、USERNAME_FIELD を変更します。

from django.contrib.auth.models import AbstractUser
from django.db import models

class User(AbstractUser):
    email = models.EmailField(unique=True, verbose_name='メールアドレス')
    phone = models.CharField(max_length=20, blank=True, verbose_name='電話番号')

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

USERNAME_FIELD'email' に変更すると、authenticate 関数や管理画面のログインがメールアドレスベースに切り替わります。email フィールドには unique=True が必須です。ログイン ID として使うフィールドに重複があってはならないためです。

REQUIRED_FIELDScreatesuperuser コマンドで入力を求められるフィールドのリストです。USERNAME_FIELD に指定したフィールドと password は自動で含まれるため、ここには含めません。

管理画面への対応

カスタムユーザーモデルを管理画面で使うには、UserAdmin を継承してカスタマイズします。

# accounts/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User

class CustomUserAdmin(UserAdmin):
    fieldsets = UserAdmin.fieldsets + (
        ('追加情報', {'fields': ('phone', 'bio', 'date_of_birth')}),
    )
    add_fieldsets = UserAdmin.add_fieldsets + (
        ('追加情報', {'fields': ('phone', 'bio', 'date_of_birth')}),
    )

admin.site.register(User, CustomUserAdmin)

UserAdmin.fieldsets に追加フィールドをタプルで連結しています。add_fieldsets はユーザー新規作成画面のフィールド設定で、こちらにも追加フィールドを含めておくと管理画面からの登録時に入力できるようになります。

AbstractBaseUser という選択肢

AbstractUser はフィールド構成をあまり変えずに拡張したい場合に最適ですが、username フィールドを完全に削除したいなど、根本的にモデル構造を変えたい場合は AbstractBaseUser を使います。

AbstractUser

標準の User モデルをそのまま継承。フィールドの追加が中心のカスタマイズに向く。認証バックエンドや権限の仕組みがすべて引き継がれるため、設定が最小限で済む。

AbstractBaseUser

パスワード管理と認証の基盤だけを提供。フィールド構成を完全に自由に設計できるが、権限の仕組み(PermissionsMixin)を自分で組み込む必要がある。

ほとんどのプロジェクトでは AbstractUser で十分です。AbstractBaseUser が必要になるのは、username フィールド自体が不要、あるいはフィールド構成を根本から設計し直したいようなケースに限られます。

カスタムユーザーモデルはプロジェクト開始時にしか安全に導入できない設定です。たとえ最初は標準の User モデルで十分に見えても、AbstractUser を継承した空のモデルだけは作っておく——これが Django 開発におけるベストプラクティスになっています。