【Django】Userモデルをカスタマイズする方法【AbstractBaseUser】

アイキャッチ画像
  • Userモデルをカスタマイズするには?
  • AbstractBaseUserの使い方とは?

本記事ではこのような疑問を解決します。


DjangoではデフォルトのUserモデルが用意されており、
ユーザーネームやメールアドレス、パスワードなどの項目があります。

しかし、一般的に提供されているWebサービスにおいて、
そのUserモデルにあたる会員情報はユーザーネームやメールアドレス、パスワードだけでは物足りないことが多いでしょう。

そのため、大抵の場合はUserモデルをカスタマイズする必要があります。


そこで今回はUserモデルをカスタマイズする方法を解説してきます。

UserモデルのカスタマイズにはAbstractBaseUserを使う

Userモデルのカスタマイズをする方法にはAbstractUserを継承する方法とAbstractBaseUser継承する方法の2つがあります。

両者の違いは以下の通りです。

○AbstractUser
カスタマイズの柔軟性は低いがコーディング量は少ない
→属性の追加変更のみをする場合に推奨される


○AbstractBaseUser
カスタマイズの柔軟性は高いがコーディング量は多い
→属性の削除やAbstractUserの範疇を超えるカスタマイズをする場合に推奨される

これはAbstractUserとAbstractBaseUserの両者の継承関係を表すと以下のようになるため、
AbstractBaseUserの方が自由度が大きいのです。

AbstractBaseUser継承関係図

そして、今回はカスタマイズ性に優れたAbstractBaseUserを使っていきます。

Userモデルのカスタマイズ手順

最初にUserモデルのカスタマイズ手順の全体像を確認しましょう。

①Userモデルを定義する


②Userモデルとして利用するテーブルを指定する


③管理画面にカスタマイズしたUserモデルを登録する

なお、今回使用するDjangoプロジェクトのアプリフォルダ名は「user_c」とします。

それでは次から具体的な手順を見ていきましょう。

①Userモデルを定義する

まずはカスタマイズしたいようにUserモデルを定義します。

今回のユーザーフィールドは以下の通りです。
・メールアドレス(ユーザ名の代わりとして使う)
・ニックネーム
・ユーザー登録日
・パスワード


ではmodels.pyにて以下のような記述をします。

from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser


class UserManager(BaseUserManager):
    
    def create_user(self, email, nickname, date_of_birth, password=None):#ユーザーのフィールドを作成
        if not email:
            raise ValueError('Users must have an email address')

        user = self.model(
            email=self.normalize_email(email),
            nickname=nickname,
            date_of_birth=date_of_birth,
        )
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, nickname, date_of_birth, password=None):#管理ユーザーのフィールドを作成
        user = self.create_user(
            email,
            password=password,
            nickname=nickname,
            date_of_birth=date_of_birth,
        )
        user.is_admin = True
        user.save(using=self._db)
        return user


class User(AbstractBaseUser):
    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
    )
    nickname = models.CharField(max_length=150)
    date_of_birth = models.DateField()
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['nickname', 'date_of_birth']

    def __str__(self):
        return self.email

    def has_perm(self, perm, obj=None):#Trueを返して、権限があることを知らせる
        return True

    def has_module_perms(self, app_label):#Trueを返して、アプリ(App)のモデル(Model)へ接続できるようにする
        return True

    @property
    def is_staff(self):#Trueの場合、Django管理サイトにログインできる
        return self.is_admin

記述が完了したら、makemigrations・migrateコマンドを実行してデータベースに内容を反映させましょう。

②Userモデルとして利用するテーブルを指定する

次にUserモデルとして利用するテーブルを指定します。

settings.pyにて以下のような記述をします。

AUTH_USER_MODEL = 'user_c.User'

AUTH_USER_MODELには、デフォルトで使用する認証Userモデルを指定します。

‘アプリ名.テーブル名’という形式で指定するため、ここでは’user_c.User’と記述します。

③管理画面にカスタマイズしたUserモデルを登録する

最後にカスタマイズしたUserモデルを管理画面で扱えるように登録をしていきます。

admin.pyにて以下のような記述をします。

from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.core.exceptions import ValidationError
from .models import User


class UserCreationForm(forms.ModelForm):#ユーザー登録フォームを作成

    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)

    class Meta:
        model = User
        fields = ('email', 'nickname', 'date_of_birth')

    def clean_password2(self):#確認用パスワードが合致するかチェック
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise ValidationError("Passwords don't match")
        return password2

    def save(self, commit=True):#パスワードを生成
        user = super().save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user


class UserChangeForm(forms.ModelForm):#ユーザー更新フォームを作成

    password = ReadOnlyPasswordHashField()

    class Meta:
        model = User
        fields = ('email', 'password', 'nickname', 'date_of_birth', 'is_active', 'is_admin')


class UserAdmin(BaseUserAdmin):#Django管理サイトの画面を編集

    form = UserChangeForm
    add_form = UserCreationForm

    list_display = ('email', 'nickname', 'date_of_birth', 'is_admin')
    list_filter = ('is_admin',)
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Personal name', {'fields': ('nickname',)}),
        ('Personal info', {'fields': ('date_of_birth',)}),
        ('Permissions', {'fields': ('is_admin',)}),
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'nickname', 'date_of_birth', 'password1', 'password2'),
        }),
    )
    search_fields = ('email',)
    ordering = ('email',)
    filter_horizontal = ()


admin.site.register(User, UserAdmin)#Django管理サイトへUserモデルとUserAdminを登録
admin.site.unregister(Group)#Django管理サイトからGroupモデルの削除

Userモデルのカスタマイズが反映されているかを管理画面で確認しよう!

最後にUserモデルのカスタマイズが反映されているかをDjango管理サイトの画面で確認しましょう。

まずDjango管理サイトへログインするためにcreatesuperuserコマンドで管理ユーザーを生成します。

管理ユーザー生成後、Django管理サイトへログインすると以下のようにUserモデルおよび管理画面がカスタマイズされていることが確認できます。

カスタムUserモデル画面①
カスタムUserモデル画面②

以上AbstractBaseUserを使うことでUserモデルをカスタマイズすることができました。

なお、会員登録機能についてはこちらの記事を参考にしてみてください。

関連記事

Djangoで会員登録機能を実装するには?UserCreationFormの使い方とは? 本記事ではこのような疑問を解決します。多くのWebサービスでは会員登録機能が実装されています。会員登録機能は顧客情報の獲得や収益化などのビジネ[…]

アイキャッチ画像
関連記事

Djangoが学べるプログラミングスクールとは?おすすめのDjangoスクールとは? 本記事ではこのような疑問を解決します。DjangoはPythonで作られた中で1番メジャーなWebフレームワークです。みんなが普段利用するYouT[…]

アイキャッチ画像