Contents
DjangoのデフォルトUserモデルの限界とカスタマイズの必要性
デフォルトUserモデルは、ユーザー名(username)を識別子として扱う仕様です。しかし、現代のWebアプリケーションでは「メールアドレスで登録・ログイン」が当たり前となっています。さらに、プロフィール画像や所属部署などの追加情報を格納する必要性も高まっています。
メールアドレス認証の制約
デフォルトモデルはユーザー名を唯一の識別子として扱うため、メールアドレスでのログインにはカスタムが必要です。たとえば、SaaS向けサービスではユーザーが「@example.com」形式で登録するケースが多いため、認証フローの再設計が求められます。
独自フィールド追加の困難さ
既存モデルにProfileなどの関連モデルを追加することは可能ですが、ユーザー情報自体に必要なデータ(住所、誕生日)などを直接格納するにはカスタムモデルが必要です。また、Django Adminでの管理画面表示や検索条件も柔軟性が欠如します。
AbstractBaseUserとAbstractUserの選択基準
カスタムユーザーモデルを作成する際は、AbstractBaseUserかAbstractUserかを選びます。両者は目的に応じた使い分けが必要です。
完全なカスタムが必要な場合
AbstractBaseUserは完全にカスタマイズ可能な基底クラスで、ユーザー名とパスワード以外のすべてのフィールドを自前で定義します。例として、メールアドレスのみを識別子とする認証フローを作成する際には適しています。
既存フィールドを拡張する場合
AbstractUserはデフォルトモデルに加えて独自フィールドを追加できるクラスです。たとえば、ユーザー名やパスワードの他に「住所」や「電話番号」などのフィールドを追加する場合に使われます。
| 比較項目 | AbstractBaseUser |
AbstractUser |
|---|---|---|
| フィールドのカスタマイズ性 | 完全カスタム可能 | 一部のみ拡張可能 |
| 認証ロジックの再定義 | 必要 | 不要(デフォルト使用) |
| 使用例 | メールアドレス認証 | 所属部署の追加など |
注意点:
AbstractUserを継承する場合、usernameフィールドは必須です。メールアドレス認証を行うには別途カスタムが必要です。
settings.pyでのAUTH_USER_MODEL設定手順
カスタムモデルを作成した後は、settings.pyで使用するモデルを指定します。この設定がなかった場合、DjangoはデフォルトのUserモデルを使用し、マイグレーションが失敗する可能性があります。
正しい参照方法
AUTH_USER_MODELにカスタムモデルを指定する際、アプリケーション名とモデル名を「.」でつなぐ形式で記述します。たとえば以下のような設定になります。
|
1 2 3 4 |
# settings.py AUTH_USER_MODEL = 'accounts.CustomUser' |
マイグレーション前の確認点
- モデルファイル(例:
models.py)に定義したクラス名が正しいかを確認する - マイグレーション作成前に
makemigrationsを実行しないこと(後述の手順で行う)
カスタムモデルのデータベースマイグレーション
カスタムモデルを定義してから、Djangoにデータベース構造を反映させる必要があります。このステップが飛ばされると、アプリケーション起動時にエラーが発生します。
makemigrationsコマンドの実行
以下のコマンドでマイグレーションファイルを作成します。
|
1 2 |
python manage.py makemigrations |
- 作成された
0001_initial.pyなどのファイルに、カスタムモデルの構造が記載されます
migrateによるDB更新
作成したマイグレーションファイルを実行して、データベースを作成します。
|
1 2 |
python manage.py migrate |
注意点:既存ユーザーがいる場合、このステップでは新規レコードのみが生成され、旧Userモデルのデータは移行されません(次項で詳述)
既存ユーザーデータの移行方法
既存のauth_userテーブルに格納されているユーザーをカスタムモデルへコピーするには、手動でのクエリ実行またはスクリプトによる自動処理が必要です。
データコピーのためのクエリ
以下は、auth_userからCustomUserにデータを転送する例です(メールアドレスが識別子となる場合)。
|
1 2 3 4 5 6 7 8 9 10 11 |
from django.contrib.auth.models import User from accounts.models import CustomUser for user in User.objects.all(): CustomUser.objects.create( email=user.email, password=user.password, # 注意: パスワードハッシュは移行不可 first_name=user.first_name, last_name=user.last_name, ) |
注意点:
passwordフィールドのハッシュ値は、デフォルトUserモデルとカスタムモデル間で互換性がないため、リセットが必要です。このリスクを無視すると、既存ユーザーがログインできなくなる可能性があるため、必ず事前に全員のパスワードを再設定してください。
データ整合性の確認手順
- 移行後のレコード数を
CustomUser.objects.count()で確認 - 一意なメールアドレスが重複していないかチェック
- 管理画面やカスタムビューからログイン可能かテスト
実践例:認証フローのカスタマイズ
カスタムモデルを導入した後は、認証フローに合わせてUserManagerとforms.pyをオーバーライドします。以下はメールアドレスをベースとした登録・ログイン機能の実装例です。
カスタム UserManager の作成
カスタムモデル用のManagerを作成し、メールアドレスでユーザーを検索する処理を定義します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
from django.contrib.auth.models import BaseUserManager class CustomUserManager(BaseUserManager): def create_user(self, email, password=None, **extra_fields): if not email: raise ValueError('The Email must be set') email = self.normalize_email(email) # メールアドレスを正規化(例: lowercase) user = self.model(email=email, **extra_fields) user.set_password(password) user.save() return user def create_superuser(self, email, password=None, **extra_fields): extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) return self.create_user(email, password, **extra_fields) |
forms.py でのオーバーライド
ログイン用のAuthenticationFormをカスタムし、emailフィールドをusernameフィールドと置き換えるようにします。
|
1 2 3 4 5 6 7 8 9 |
from django import forms from django.contrib.auth.forms import AuthenticationForm from django.contrib.auth import get_user_model User = get_user_model() class EmailAuthenticationForm(AuthenticationForm): username = forms.EmailField(label="メールアドレス") |
注意点:
get_user_model()を使うことで、カスタムモデルの変更にも柔軟に対応できます。
まとめ
本記事では、Djangoでカスタムユーザーモデルを導入する理由と具体的な実装手順を解説しました。
- デフォルトUserモデルの限界(メールアドレス認証や独自フィールド追加)
AbstractBaseUserとAbstractUserの使い分けAUTH_USER_MODELの正しく設定方法とマイグレーションフロー- 既存ユーザーデータの移行手順と注意点
- 実務での認証フローのカスタマイズ事例
プロジェクトに応じた適切なモデル設計は、後々の拡張性や保守性に大きく影響します。Django カスタムユーザーモデル 作り方を理解し、実装に挑戦してください。