- 1 Userモデルをカスタマイズ
- 2 Userの関係について
- 3 カスタムユーザーを作成する
- 4 おまけ : AbstractUserを継承してカスタムユーザーを作成する場合
- 5 作成したアプリケーションのディレクトリ構造
- 6 終わりに
Userモデルをカスタマイズ
Django Adminでは管理サイトにログインするユーザーの管理などを行えるUserモデルがデフォルトで定義されています。しかし、デフォルトのUserモデルではカスタマイズが行うことができず、プロジェクト開始後に要件の変更があったとしてもUserモデルの拡張を行うことができません。そのためプロジェクト初期の段階ではデフォルトモデルで十分な場合でも、カスタムユーザーモデルのセットアップをマイグレーションを行う前に設定することがDjangoの公式ドキュメントでも推奨されています。
参考 : Django
Userの関係について
ここでカスタムユーザーを作成するために必要な要素について理解しやすくするために、デフォルトのUserモデルの継承について整理します。Userの継承は以下の図の様になってます。
実際にカスタムユーザーを作成する場合、AbstractUserを継承する方法を、AbstractBaseUserとPermissionsMixinの2つを継承する方法があります。
デフォルトのものにフィールドやメソッドを付け加えていきたいなら、AbstractUserを継承してカスタムユーザーを作成しましょう
AbstractUser周りで継承されているフィールドが必要なければAbstractBaseUserとPermissionsMixinを継承してカスタムユーザーを作成しましょう。
今回はより複雑なAbstractBaseUserとPermissionsMixinを継承する方法を元に解説していきます。
カスタムユーザーを作成する
ここからは実際にカスタムユーザーを作成する手順について紹介します。
カスタムユーザー用のアプリケーションを作成する
カスタムユーザーモデルの定義を行うアプリケーションauthorizationの作成をします。
python manage.py startapp authorization
作成が完了したら、setting.pyのINSTALL_APPSに作成したアプリであるauthorizationの追加を行います。
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"authorization",
]
AbstractBaseUserとPermissionsMixinを継承したCustomUserの作成を行う
作成したアプリケーションauthorizationのmodel.pyにCustomUserモデルを以下のように定義します。
from django.db import models
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.models import BaseUserManager
class CustomUserManager(BaseUserManager):
def get_by_natural_key(self, username):
return self.get(username=username)
def create_superuser(self, username, password=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(username, password, **extra_fields)
def _create_user(self, username, password=None, **extra_fields):
if not username:
raise ValueError('The Username field must be set')
user = self.model(username=username, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
class CustomUser(AbstractBaseUser, PermissionsMixin):
username = models.CharField(verbose_name="ユーザーネーム", unique=True, max_length=100)
is_staff = models.BooleanField(default=False)
objects = CustomUserManager()
USERNAME_FIELD = 'username'
CustomUserクラス
フィールドの定義
username = models.CharField(unique=True,max_length=100)
is_staff = models.BooleanField(default=False)
認証時に使用するフィールドとしてCharField型のusernameと管理サイトにログイン可能を判別するためのフィールドとしてBooleanField型のis_staffを定義しています。注意点としては、is_staffはAbstractBaseUserとPermissionsMixinにて扱われていませんが、定義しない場合、管理サイトにログインできなくなってしまうので、管理サイトを作成する場合には必ず定義するようにしましょう。
USERNAME_FIELDの指定
USERNAME_FIELD = 'username'
USERNAME_FIELD属性を利用することで、認証時に使用するフィールドを指定することができます。このとき使用するフィールドにはuniqueオプションを指定し、データベース全体で一意である必要があります。今回の例ではUSERNAME_FIELDにusernameというフィールドを使用していますが、uniqueなフィールドであれば、username以外のフィールドを指定して、認証時に使用することもできます。
使用するマネージャーの指定
objects = CustomUserManager()
CustomUserManagerクラスのインスタンスを作成し、カスタムユーザーモデルでの、データベースとのやり取りやクエリの実行、データの作成、更新、削除などの操作を行うマネージャーオブジェクトの作成を行います。objectsという名前は、Djangoのソースコード内でマネージャーを指定する際に使用される標準的な名前になっています。マネージャーが必要となる点はAbstractBaseUserとPermissionsMixinを継承する際に見落しがちな点なのでご注意ください。
CustomUserManagerクラス
CustomUserで使用するマネージャーのクラスを作成します。管理サイトにログインできるユーザーを作成するためにはcreatesuperuserコマンドを実行できるようにする必要があるため、少なくとも_create_userメソッドとcreate_superuserメソッドを作成する必要があります。
_create_userメソッドの作成
def _create_user(self, username, password=None, **extra_fields):
if not username:
raise ValueError('The Username field must be set')
user = self.model(username=username, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
新しいユーザーを作成するときに使用するメソッドです。このメソッドは後述するcreate_superuserメソッドで使用するため、作成する必要があります。
create_superuserメソッドの作成
def create_superuser(self, username, password=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(username, password, **extra_fields)
新しいスーパーユーザーを作成するときに使用するメソッドです。createsuperuserコマンドを実行した場合には、is_staffとis_superuserをTrueにしてユーザーの作成を行います。
このメソッドがない場合、createsuperuserコマンドが実行できず、スーパーユーザーの作成が行えないため、管理サイトにログインすることができなくなります。
管理画面にCustomUserモデルを表示する
authorizationのadmin.pyに以下の以下のコードを記述します。
from django.contrib import admin
from .models import CustomUser
class CustomUserAdmin(admin.ModelAdmin):
list_display = (
"username",
"is_staff",
"is_superuser",
)
fieldsets = (
("基本情報", {"fields": ("username", "password")}),
(
"権限情報",
{
"fields": (
"is_staff",
"is_superuser",
"groups",
"user_permissions",
),
},
),
("日時情報" , {"fields": ["last_login"]}),
)
admin.site.register(CustomUser, CustomUserAdmin)
認証に使用するモデルとしてCustomUserモデルを指定する
setting.pyのAUTH_USER_MODELにCustomUserモデルを指定して、認証に使用するモデルを変更します。
AUTH_USER_MODEL = 'authorization.CustomUser'
モデルのマイグレーションを行う
マイグレーションコマンドを実行し、変更したモデルを反映します。
python manage.py makemigrations
python manage.py migrate
Tips
以前の認証に使用したモデルでマイグレーションを行っていると、エラーが起こります。そのような場合には、各アプリケーションのmigrations以下にある__init__.py以外のファイルの削除を行ったあと、dbの削除を行いましょう。dbの削除はデフォルトの状態であれば、db.sqlite3を削除することで実行できます。こちらの方法を使用すると、今まで入力してきたデータが無くなるため、カスタムユーザーモデルのセットアップをマイグレーションを行う前に設定することがDjangoの公式ドキュメントで推奨されているのだと思われます。先にカスタムユーザーを作成したあとであれば、フィールドの追加等のカスタマイズも可能なためカスタムユーザーの作成は優先して行いましょう。
スーパーユーザーを作成する
createsuperuserコマンドを実行して作成したカスタムユーザーモデルを元に管理者ユーザーが作成できることを確認しましょう。
python manage.py createsuperuser
ユーザーネーム: admin
Password:
Password (again):
Superuser created successfully.
おまけ : AbstractUserを継承してカスタムユーザーを作成する場合
作成したアプリケーションauthorizationのmodel.pyにCustomUserモデルを以下のように定義します。
class CustomUser(AbstractUser):
first_name = None
last_name = None
full_name = models.CharField(max_length=100)
class Meta:
db_table = 'custom_user'
この方法の場合、AbstractBaseUserとPermissionsMixinやAbstractUserに存在しているフィールドについてNoneと指定することで、そのフィールドをモデルで扱わなくすることができます。
マネージャーについてはAbstractUserで宣言されているため、マネージャーのカスタムが必要ないのであれば用意する必要はありません。
USERNAME_FIELDの使用も可能で、emailなどを識別用のフィールドとして扱うこともできます。
作成したアプリケーションのディレクトリ構造
.
├── authorization
│ ├── __init__.py
│ ├── __pycache__
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── config
│ ├── __init__.py
│ ├── __pycache__
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── db.sqlite3
└── manage.py
終わりに
今回はDjango Adminでカスタムユーザーを導入する方法について紹介しました。カスタムユーザーを導入するにはデフォルトのユーザーモデルの継承関係などを知らないと理解しにくく、難しい内容だったと思います。
他の記事でもDjango Adminについての解説をしているのでよければ合わせて御覧ください。
admin.pyに
admin.site.register(CustomUser, CustomUserAdmin)の記述が抜けており
そのままでは管理画面にCustom Uersが表示されないようなので注意が必要です。
コメントありがとうございます。
ご指摘の通り、admin.site.register(CustomUser, CustomUserAdmin) の記述が抜けていたので本文を修正いたしました。