このページでは、Django において、管理画面(admin
)でカスタムユーザーを管理する方法について解説していきます。
下記ページで解説しているとおり、AbstractUser
や AbstractBaseUser
を継承することで独自のユーザー管理モデルクラスを定義することができます。このページでは、この AbstractUser
や AbstractBaseUser
を継承して定義した独自のユーザー管理モデルクラスのことを「カスタムユーザー」と呼ばせていただきます。
さらに、下記ページで解説しているとおり、admin.py
の実装により、自身のアプリの models.py
で定義したモデルクラスを管理画面で管理できるようにすることもできます。また、ModelAdmin
のサブクラスを定義することにより、モデルクラス毎の管理画面(インスタンスの一覧表や追加・編集フォーム)を変更することも可能です。
ただし、カスタムユーザーの管理画面での管理に限れば、上記のページで解説している内容だけでは手順が実は不十分です。ModelAdmin
のサブクラスではユーザーの管理がうまく行えません。
このページでは、その理由や、カスタムユーザーを管理画面で管理するための手順について解説していきたいと思います。
カスタムユーザーの管理に ModelAdmin
が不十分である理由
まずは、カスタムユーザーの管理に ModelAdmin
が不十分である理由について解説していきます。
管理画面とは
まずは復習として、「管理画面」と「管理画面のカスタマイズ」について簡単に説明していきます。
管理画面とは、通常下記の URL からアクセスできるページのことになります(設定変更等により管理画面の URL は変更することも可能です)。
http://localhost:8000/admin/
実際の画面は下図のようなものになります。
管理画面自体の説明や管理画面の使い方については下記ページで解説していますので、詳しくは下記ページをご参照いただければと思います。
【Django入門11】管理画面(admin)の使い方の基本ポイントは、管理画面では各モデルクラスのインスタンスの管理が行えるという点になります。
スポンサーリンク
管理画面のカスタマイズ
ただし、デフォルトでは管理画面で管理できるモデルクラスは auth
というアプリから提供される Group
と User
のみとなっています。
ですが、admin.py
を変更することにより、他のモデルクラスも管理画面で管理できるようになります。さらに、このモデルクラスの管理画面は ModelAdmin
というクラスに従って表示されるようになっています。そして、モデルクラス毎の管理画面を ModelAdmin
のサブクラスの定義により変更することも可能となっています。
この辺りについては下記ページで詳細を解説していますので、詳しく知りたい方は下記ページを読んでみていただければと思います。
【Django入門12】管理画面のカスタマイズ(ModelAdmin)ただし、このページの冒頭でも触れたように、カスタムユーザーに関しては、管理画面の表示に ModelAdmin
や ModelAdmin
のサブクラスを利用しても、基本的には管理が上手くできません。
問題点:ModelAdmin
では暗号化が行われない
この決定的な理由の1つはパスワード管理になります。カスタムユーザー等のユーザーを管理するモデルクラスは、認証を行うためにパスワードフィールドを持つようになっています。
そして、このパスワードフィールドの文字列は、セキュリティ面から考えるとデータベースに保存される際には暗号化されている方が望ましいです。
簡単のため暗号化と表記していますが、実際には SHA256 というアルゴリズムでハッシュ化が行われることになります
したがって、パスワードを保存する際には、パスワードフィールドの文字列の暗号化が必要となります。これは、カスタムユーザーにおいても、User
においても同様です。
ですが、ModelAdmin
を利用した管理画面でパスワードを保存したとしても、基本的にはパスワードは平文のまま暗号化されずに保存されます。まず、この時点でセキュリティ的にアウトです。
そして、セキュリティだけでなく、平文でパスワードが保存されることは機能的にも問題となります。前述の通り、パスワードはユーザー認証を行う際に利用されます。
例えばログインを行う際にユーザー認証が利用されます。そして、ユーザー認証が行われる際には、ログインフォームのパスワードフィールドに入力された文字列を暗号化した結果と、データベースに保存されているパスワードの比較が行われます。
データベースにパスワードを保存する際に行う暗号化と、ログインフォームに入力されたパスワードの暗号化では同じアルゴリズムが用いられます。そのため、「ログインフォームに入力されたパスワードが正しい」&「データベースに保存されているパスワードが暗号化されている」場合は認証に成功することになります。
ですが、そもそもデータベースに保存されているパスワードが平文の場合、ログインフォームに入力されたパスワードが正しくても認証には成功しません。これは、ログインフォームに入力されたパスワードは暗号化されるため、暗号化された文字列と平文の文字列とを利用して認証が行われてしまうことになるからです。
逆に、ログインフォームに入力されたパスワードが間違っていても、認証に成功してしまうようなケースもあり得ます。
このように、データベースに保存されるパスワードが平文である点は、認証機能を正常に動作させるという点においても問題になります。
ModelAdmin
で User
を管理した時の動作
せっかくなので、この問題点を実際に確認してみましょう。確認が不要という方は、次の カスタムユーザーを管理する方法 にスキップしていただければと思います。
プロジェクトとアプリの作成
まず、適当な作業フォルダに移動し、下記のコマンドで testmodeladmin
プロジェクトを作成してください。
% django-admin startproject testmodeladmin
続いて、下記のコマンドで testmodeladmin
フォルダ内に移動し、
% cd testmodeladmin
さらに下記のコマンドで accounts
アプリを作成してください。
% python manage.py startapp accounts
models.py
と admin.py
の変更
このコマンドの実行によって accounts
フォルダが作成され、その中に models.py
というファイルが存在するはずですので、このファイルを開いて下記のように変更して保存してください。CustomUser
が、このページの題材となっているカスタムユーザーとなります。
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
pass
さらに、accounts
フォルダ内には admin.py
というファイルが存在するはずですので、このファイルを開いて下記のように変更して保存してください。下記のように admin.site.register
を実行することで、CustomUser
が管理画面での管理対象として登録されることになります。また、admin.site.register
に第2引数を指定していないため、この CustomUser
の管理画面は ModelAdmin
の定義に基づいて表示されることになります。
from django.contrib import admin
from .models import CustomUser
admin.site.register(CustomUser)
プロジェクトの設定
次に、accounts
フォルダと同階層(つまり今いるフォルダ内)に testmodeladmin
というフォルダが存在し、その中に settings.py
というファイルがあるはずですので、このファイルを開き、まずはINSTALLED_APPS
を下記のように変更してください。1行目に 'accounts',
を追加してやれば良いだけです。
INSTALLED_APPS = [
'accounts',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
さらに、ファイルの末尾に下記を追加して保存してください。
AUTH_USER_MODEL = 'accounts.CustomUser'
以上により、カスタムユーザー CustomUser
が定義され、このモデルクラスによって認証が行われるようになったことになります。さらに、admin.py
の変更により、管理画面で CustomUser
を管理できるようになったことになります。前述の通り、admin.site.register
には第2引数を指定していないため、CustomUser
に対する管理画面は ModelAdmin
クラスに基づいて表示されることになります。
次は、管理画面を利用するための準備を行なっていきます。
マイグレーションとスーパーユーザの作成
まずは、下記の2つのコマンドを実行してマイグレーションを実行しましょう。
% python manage.py makemigrations % python manage.py migrate
続いて、下記のコマンドを実行してスーパーユーザーを作成します。ユーザー名とメールアドレスとパスワード2回を入力してください(パスワードやメールアドレスが出鱈目だと妥当でないと判断される可能性もあるので注意してください)。
% python manage.py createsuperuser
ちなみに、スーパーユーザーとは何なのか?という点に関しては下記ページで解説していますので、詳しく知りたい方は読んでみてください。
【Django入門11】管理画面(admin)の使い方の基本また、上記の createsuperuser
コマンドではパスワードの入力を行っていますが、このパスワードに関しては暗号化されて保存されるようになっています。平文で保存されるのは、あくまでも管理画面でのユーザー作成時の話になります(さらに ModelAdmin
を利用している場合の話)。
スーパーユーザーでのログイン
次に、下記コマンドで開発用サーバーを起動すれば、管理画面を利用できる準備が整ったことになります。
% python manage.py runserver
ということで、次は管理画面を利用していきます。まずはウェブブラウザを起動し、下記の URL を開いてください。
http://localhost:8000/admin/
ログインフォームが表示されるはずですので、先ほど作成したスーパーユーザーのユーザー名とパスワードを入力して Log in
ボタンをクリックしてください。
このログイン時には、前述の通りユーザー認証が行われることになります。先ほども説明したように、createsuperuser
コマンドで作成したユーザーのパスワードはデータベースに暗号化された状態で保存されるため、正しいパスワードを入力されれば、認証に成功してログインできるはずです。
ログイン後は下図のようなページが表示されると思います(色味などは違うかも…)。
管理画面でのユーザーの追加
次は、CustomUser
のインスタンスの追加を行なってみましょう!Users
の右側にある Add
リンクをクリックしてください。現状の設定だと、管理画面においては CustomUser
は User
or Users
として表示されています。
すると、CustomUser
のインスタンス追加フォームが表示されるはずですので、ここでは下記を入力してページ下部にある SAVE
ボタンをクリックしてください(そもそも、この入力時にパスワードが丸見えになっている時点でセキュリティ的に問題があることが確認できると思います…)。
Password
:適当なものSuperuser status
:チェック ON に変更Username
:適当なものStaff status
:チェック ON に変更
Staff status
と Superuser status
にチェックを ON している理由は、追加する CustomUser
に管理画面での全管理の権限を与えるためになります。つまり、本来であれば、上記のように設定して作成したユーザーは管理画面へのログインを行うことが可能となるはずです。が、前述の通り、パスワードの暗号化が行われないことが原因でログインできなくなってしまっています。
このログイン不可であることを確認する前に、追加したユーザーの情報を見てみましょう!
追加フォームで SAVE
ボタンをクリックした後、画面左側にある Users
をクリックすれば CustomUser
のインスタンスの一覧が表示されることになります。ここで、先ほど追加したインスタンスのユーザー名をクリックしてみてください。
おそらく、下の図のようにパスワードが平文で表示されていることが確認できると思います。
次は、先ほどの一覧表から createsuperuser
で追加したインスタンスのユーザー名をクリックしてください。この場合は、パスワードが意味不明な文字列になっており、パスワードが暗号化されていることが確認できるはずです。
このように、現状の管理画面の CustomUser
フォームでインスタンスを追加した場合、パスワードが平文で保存されていることになります。流石にパスワードが平文で丸見え状態で保存されているアプリを使いたいとは思えないですよね…。
管理画面で追加したユーザーでのログイン
さらに、平文でパスワードが保存されると認証機能もうまく動作しません。次はログイン時の認証の動作を確認してみましょう!
まず、管理画面のページの上部にある LOG OUT
リンクをクリックしてください。これによりログインしていたスーパーユーザーのログアウトが行われます。さらに、リンククリック後に表示されるページの Log in again
リンクをクリックしてください。
これにより、再度ログインフォームが表示されることになります。ここでは、先ほど管理画面の追加フォームで追加したユーザーのユーザー名とパスワードを入力して Log in
ボタンをクリックしてください。
すると、下の図のようにログインに失敗してしまうことになるはずです。
このようにログインに失敗するのは、あなたがパスワードの入力を間違ったことが原因ではなく、インスタンス追加時にパスワードが平文で保存されてしまったことが原因となります。
つまり、ログインできない原因はインスタンスの追加フォームに問題があります。そして、この追加フォームは ModelAdmin
に従って表示されているため、結局は ModelAdmin
が悪いということになります。悪いというよりも、パスワードを扱うようなモデルクラスの管理画面としては ModelAdmin
は不十分ということになります。
スポンサーリンク
カスタムユーザーを管理する方法
ちょっと説明が長くなってしまいましたが、カスタムユーザーの管理に ModelAdmin
が不十分である理由の解説は以上となります。
では、カスタムユーザー向けの管理画面はどのようにして実現すれば良いのでしょうか?その点について解説していきたいと思います。
UserAdmin
のサブクラスを利用する
結論を言うと、カスタムユーザーを管理するためには ModelAdmin
ではなく UserAdmin
のサブクラスを利用するようにしてやれば良いです。
つまり、admin.py
を下記のように変更してやれば良いことになります。CustomUserAdmin
が UserAdmin
のサブクラスとなります。一旦、CustomUserAdmin
の中身の定義は pass
としていますが、UserAdmin
のサブクラスの実装については後述で解説していきます。
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser
class CustomUserAdmin(UserAdmin):
pass
admin.site.register(CustomUser, CustomUserAdmin)
UserAdmin
とは
いきなり UserAdmin
というクラスが登場しましたが、この UserAdmin
とはどのようなクラスなのでしょうか?
一言で言えば、User
の管理画面を実現するためのクラスとなります。
前述の通り、通常のモデルクラスの管理画面は ModelAdmin
によって実現されることになります。そして、ModelAdmin
のサブクラスを定義することで、モデルクラス毎に管理画面を変更することが可能となります。例えば、インスタンスの一覧表示ページやインスタンスの追加・編集フォームの変更を行うようなことができます。
UserAdmin
は、まさに、その ModelAdmin
のサブクラスの1つとなります。これは auth
アプリで定義されているクラスで、User
の管理を行うことに特化したクラスとなっています。
また、下記ページを読んでくださった方であれば分かると思いますが、管理画面では User
のインスタンスの追加を行うことが可能で、User
の追加フォームから追加した場合、そのユーザーでのログインが可能となっています(ログインするためにはユーザーの Staff status
のチェックを ON しておく必要があります)。
そして、この User
の追加フォームは UserAdmin
に従って表示されるものになります。つまり、UserAdmin
の追加フォームを利用すれば、ModelAdmin
の時とは異なりログイン可能なユーザーを作成することができます。もちろん、パスワード保存時の暗号化も行われますし、パスワード入力時には入力した文字列がマスクされて表示されることにもなります。
追加フォームだけでなく、UserAdmin
の編集フォームでもパスワード保存時の暗号化やパスワード入力時のマスク処理が行われるようになっています。
したがって、カスタムユーザーの管理においても、ModelAdmin
ではなく UserAdmin
のサブクラスが利用されるようにすれば、ログイン等も可能なカスタムユーザーの追加・編集が可能となることになります。
スポンサーリンク
UserAdmin
のサブクラスが必要な理由
で、ここまで説明してきた通り、カスタムユーザーの管理画面を実現するためには、UserAdmin
そのものではなく、UserAdmin
の “サブクラス” を定義して利用することになります。UserAdmin
でもパスワードの暗号化等が行われるのに、なぜわざわざサブクラスを定義する必要があるのでしょうか?
それは、UserAdmin
はあくまでも User
の管理画面を実現するためのクラスとなっているからになります。
もっと具体的に言えば、UserAdmin
は User
の持つフィールドに合わせたインスタンスの一覧表やフォームの表示が行われるように実装されています。したがって、カスタムユーザーの管理画面を UserAdmin
で実現しようとした場合、User
の持つフィールドをカスタムユーザーが持っていないと画面表示時に例外が発生することになります。
逆に、 User
の持たないフィールドをカスタムユーザーに追加した場合でも、その追加したフィールドは一覧表やフォームには表示されないことになります。
このように、UserAdmin
はあくまでも User
の管理画面を実現するためのクラスです。そのため、カスタムユーザーの管理を行う際は UserAdmin
をそのまま利用するのではなく、UserAdmin
のサブクラスを定義し、そのサブクラスでカスタムユーザーと User
の差を吸収するように実装を行う必要があります。
もっと具体的に言えば、カスタムユーザーの持たないフィールドが参照されないように UserAdmin
のクラス変数を上書きしたり、カスタムユーザーのみに存在するフィールドが表示されるように UserAdmin
のクラス変数を上書きしたりする必要があります。
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser
class CustomUserAdmin(UserAdmin):
#CustomUserとUserとの差を吸収する
admin.site.register(CustomUser, CustomUserAdmin)
ここまでの話をまとめると、カスタムユーザーを管理画面で管理する際には ModelAdmin
ではなく UserAdmin
のサブクラスを定義し、これをカスタムユーザーの管理に利用するように admin.py
で admin.site.register
を実行する必要があります。
UserAdmin
のサブクラスを定義する理由は、UserAdmin
の良いところ、具体的にはパスワードの暗号化などを継承しつつ、カスタムユーザーならではのクラスにカスタマイズを行うことができるからです。
もし、カスタムユーザーが User
と全く同じフィールドのみを持っているのであれば、UserAdmin
をそのまま利用しても管理画面での管理は正常に行うことができます。例えばカスタムユーザーが AbstractUser
を継承しているだけであれば、User
と同じフィールドを持つことになるため、UserAdmin
をそのまま admin.site.register
の第2引数に指定してやれば良いことになります。
また、カスタムユーザーの管理を ModelAdmin
のサブクラスによって実現することも可能だと思います。そのサブクラスの定義によってパスワードの暗号化やパスワードのマスクなどの処理を実現してやれば、少なくとも暗号化の問題は解決できるはずです。
ですが、せっかく UserAdmin
という便利なクラスが存在しているので、それを利用した方が楽に、かつ、品質も高いカスタムユーザーの管理を実現することができるため、このページでは UserAdmin
を利用することをオススメしています。
また、下記ページでも解説しているとおり、通常のモデルクラスの管理画面は ModelAdmin
のサブクラスの定義によって変更を行うことになります。
今回は UserAdmin
のサブクラスを利用することになりますが、実は通常のモデルクラスの時の「モデルクラスの管理画面は ModelAdmin
のサブクラスの定義によって変更する」という方針は変わっていません。前述の通り、UserAdmin
は ModelAdmin
のサブクラスですので、UserAdmin
のサブクラスも ModelAdmin
のサブクラスと考えられます。したがって、結局はカスタムユーザーの管理画面も ModelAdmin
のサブクラスの定義によって実現していくことになります。
UserAdmin
のサブクラスの実装
ここまでの説明で、カスタムユーザーを管理するために UserAdmin
のサブクラスの定義が必要であることは理解していただけたのではないかと思います。
また、UserAdmin
のサブクラスをどのように定義すれば良いのか?についてもイメージは湧いているのではないかと思います。要は、User
とカスタムユーザーの差を吸収するように定義してやれば良いです。
じゃあ、具体的にどんな実装をすれば良いの?という点について、ここから説明していきたいと思います。
今回、カスタムユーザー向けの管理画面を実現するクラスの名前は CustomUserAdmin
として説明していきます。
また、実例があった方が良いと思うので、下記の CustomUser
を管理することを想定し、この CustomUser
に応じた管理画面を作成する実例を踏まえながら解説をしていきたいと思います(UserManager
も一応用意しています)。
from django.db import models
from django.contrib import auth
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
from django.core.mail import send_mail
from django.contrib.auth.hashers import make_password
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import PermissionsMixin
class UserManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
"""
Create and save a user with the given email and password.
"""
if not email:
raise ValueError("The given email must be set")
email = self.normalize_email(email)
# Lookup the real model class from the global app registry so this
# manager method can be used in migrations. This is fine because
# managers are by definition working on the real model.
user = self.model(email=email, **extra_fields)
user.password = make_password(password)
user.save(using=self._db)
return user
def create_user(self, email=None, password=None, **extra_fields):
extra_fields.setdefault("is_staff", False)
extra_fields.setdefault("is_superuser", False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email=None, 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(email, password, **extra_fields)
def with_perm(
self, perm, is_active=True, include_superusers=True, backend=None, obj=None
):
if backend is None:
backends = auth._get_backends(return_tuples=True)
if len(backends) == 1:
backend, _ = backends[0]
else:
raise ValueError(
"You have multiple authentication backends configured and "
"therefore must provide the `backend` argument."
)
elif not isinstance(backend, str):
raise TypeError(
"backend must be a dotted import path string (got %r)." % backend
)
else:
backend = auth.load_backend(backend)
if hasattr(backend, "with_perm"):
return backend.with_perm(
perm,
is_active=is_active,
include_superusers=include_superusers,
obj=obj,
)
return self.none()
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_("email address"), unique=True)
is_staff = models.BooleanField(
_("staff status"),
default=False,
help_text=_("Designates whether the user can log into this admin site."),
)
height = models.FloatField()
weight = models.FloatField()
objects = UserManager()
EMAIL_FIELD = "email"
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["height", "weight"]
class Meta:
verbose_name = _("user")
verbose_name_plural = _("users")
#abstract = True
def clean(self):
super().clean()
self.email = self.__class__.objects.normalize_email(self.email)
def email_user(self, subject, message, from_email=None, **kwargs):
"""Send an email to this user."""
send_mail(subject, message, from_email, [self.email], **kwargs)
この CustomUser
は AbstractBaseUser
と PermissionsMixin
を継承して作成したカスタムユーザーモデルであり、AbstractBaseUser
と PermissionsMixin
を継承してカスタムユーザーを作成する手順は下記ページで解説していますので、カスタムユーザーの作り方について知りたい方は下記ページをご参照いただければと思います。
少し説明を加えておくと、上記の CustomUser
では、User
に比べて下記のフィールドを削除しています。
username
first_name
last_name
is_active
date_joined
さらに、User
に比べて下記のフィールドを追加しています。そして、これらのフィールドは必須フィールドとして設定しています(必須フィールドなので一応 REQUIRED_FIELDS
にもこれらのフィールドを追加しています)。
height
weight
基本的に User
と CustomUser
の違いは、上記のフィールドの有無のみとなります。
前述の通り、UserAdmin
は User
を管理することを前提としたクラスとなっていますので、UserAdmin
のサブクラスである CustomUserAdmin
を “上記のフィールドの有無の違いを考慮しながら” 実装していくという点が、カスタムユーザー向けの管理画面の実現を行う上でのポイントになります。
CustomUserAdmin
の定義
では、続いて本題の CustomUserAdmin
の定義を行なっていきます。
定義先のファイルはアプリフォルダ内の admin.py
となります。ひとまず、単に UserAdmin
を継承するだけのクラスとして、下記のように CustomUserAdmin
を定義したいと思います。
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
class CustomUserAdmin(UserAdmin):
pass
CustomUser = get_user_model()
admin.site.register(CustomUser)
前述の通り、CustomUserAdmin
は UserAdmin
を継承するのみで作成しているため、UserAdmin
同等のクラスになります。
ですので、このままだと User
を管理することを前提としたクラスになってしまっていますので、User
ではなく CustomUser
を管理できるようにカスタマイズしていく必要があります。
スポンサーリンク
CustomUserAdmin
の管理画面への登録
カスタマイズを行う前に、まずは CustomUser
に対する管理画面の表示時に CustomUserAdmin
が利用されるように、CustomUserAdmin
の管理画面への登録を行いたいと思います。
この登録は、下記のように admin.site.register
の第2引数に CustomUserAdmin
を指定することで実現することができます。
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
class CustomUserAdmin(UserAdmin):
pass
CustomUser = get_user_model()
admin.site.register(CustomUser, CustomUserAdmin)
admin.site.register
の第1引数では、管理画面で管理を行うモデルクラスの指定を行います。これにより、管理画面で第1引数に指定したモデルクラスのインスタンスを管理することができるようになります。
また、admin.site.register
の第2引数では、管理画面表示時に使用するクラスを指定します。これにより、管理画面が第2引数に指定したクラスに応じた画面に変化します(指定をしなかった場合は ModelAdmin
がデフォルトで指定されるようになっています)。
ですので、上記のように admin.site.register
を実行することで、CustomUser
の管理を行う画面は CustomUserAdmin
に従って表示されることになります。
ただし、現状の CustomUserAdmin
は User
のインスタンスを管理することを前提としたクラスとなっています。そのため、admin.py
を上記のように変更して Django の開発用ウェブサーバーを起動した場合、User
に対して CustomUser
のフィールドが不足しているので例外が発生することになります。
具体的に発生する例外は下記のようなものになります。
ERRORS: <class 'login_app.admin.CustomUserAdmin'>: (admin.E033) The value of 'ordering[0]' refers to 'username', which is not a field of 'login_app.CustomUser'. <class 'login_app.admin.CustomUserAdmin'>: (admin.E108) The value of 'list_display[0]' refers to 'username', which is not a callable, an attribute of 'CustomUserAdmin', or an attribute or method on 'login_app.CustomUser'. <class 'login_app.admin.CustomUserAdmin'>: (admin.E108) The value of 'list_display[2]' refers to 'first_name', which is not a callable, an attribute of 'CustomUserAdmin', or an attribute or method on 'login_app.CustomUser'. <class 'login_app.admin.CustomUserAdmin'>: (admin.E108) The value of 'list_display[3]' refers to 'last_name', which is not a callable, an attribute of 'CustomUserAdmin', or an attribute or method on 'login_app.CustomUser'. <class 'login_app.admin.CustomUserAdmin'>: (admin.E116) The value of 'list_filter[2]' refers to 'is_active', which does not refer to a Field.
ご覧の通り、User
と比較して CustomUser
に足りないフィールドに対して例外が発生していることを確認していただけると思います。
現状の CustomUserAdmin
は User
を管理することを前提としたクラスとなっているため上記のような例外が発生してしまいますが、CustomUserAdmin
を実装して例外が発生する原因となっているフィールドを利用しないようにすることで上記の例外を解消することができます。
CustomUserAdmin
の実装
ということで、次は CustomUserAdmin
で CustomUser
に存在するフィールドのみを利用するように実装していきたいと思います。
まずは、現状の把握の意味も込めて、UserAdmin
がどのようなフィールドを利用しているのかを調べたいと思います。これは、UserAdmin
の定義を表示してやることで簡単に調べることができます。
VScode 限定の話になりますが、クラスの定義の調べ方については下記ページでも紹介しているので、こちらを参考にしていただければと思います。
【Django】VSCodeでクラスの定義を簡単に確認する方法とりあえず Django 4.0.5 の場合、UserAdmin
の定義を利用するフィールドのみに焦点を当てて抜粋すると下記のようになっています。
@admin.register(User)
class UserAdmin(admin.ModelAdmin):
fieldsets = (
(None, {"fields": ("username", "password")}),
(_("Personal info"), {"fields": ("first_name", "last_name", "email")}),
(
_("Permissions"),
{
"fields": (
"is_active",
"is_staff",
"is_superuser",
"groups",
"user_permissions",
),
},
),
(_("Important dates"), {"fields": ("last_login", "date_joined")}),
)
add_fieldsets = (
(
None,
{
"classes": ("wide",),
"fields": ("username", "password1", "password2"),
},
),
)
list_display = ("username", "email", "first_name", "last_name", "is_staff")
list_filter = ("is_staff", "is_superuser", "is_active", "groups")
search_fields = ("username", "first_name", "last_name", "email")
ordering = ("username",)
上記で定義されている各クラス変数の簡単な意味合いについて解説しておきます。
fieldsets
fieldsets
はユーザーの詳細画面(編集フォーム)で表示するフィールド、および、ユーザーの情報変更を行う際に入力受付を行うフィールドを指定するクラス変数になります。
add_fieldsets
add_fieldsets
はユーザー追加フォームでユーザーからの入力を受け付けるフィールドを指定するクラス変数になります。
list_display
list_display
はユーザー一覧リストに表示するフィールドを指定するクラス変数になります。
list_filter
list_filter
は、ユーザー一覧リストに対するフィルタリング可能なフィールドを指定するクラス変数になります。
例えば、このフィルタリングを利用して is_superuser
フィールドが True
のユーザーのみをユーザー一覧リストに表示するようなことが可能です。
上の図では表示されていませんが、list_filter
に "groups"
を指定しておけば、グループが1つ以上存在する場合にフィルターの項目に By groups
が追加されます。
search_fields
search_fields
はユーザー検索を行う際に、検索対象に含めるフィールドを指定するクラス変数になります。
例えば上の図のユーザーの例で考えると、serarch_fields
に "email"
を指定している場合、abc
で検索を行うと email
に abc
が含まれるユーザー Jiro
がヒットすることになります。それに対し、serarch_fields
に "email"
を指定していない場合、email
は検索対象として扱われませんので、abc
で検索してもユーザーは一人もヒットしないことになります。
ordering
ordering
はユーザー一覧リスト初期表示時のユーザー表示順を決定するフィールドを指定するクラス変数になります。
例えば ordering
に指定するタプルの第1要素に "email"
を指定すれば、email
の文字列に対して昇順にユーザーが並んだ状態でユーザー一覧リストが表示されるようになります。
filter_horizontal
この filter_horizontal
については正直私も余り理解できていないのですが、おそらくユーザー追加時等に下図のように選択式での設定を行うことができるフィールドを指定するクラス変数になると思います。
今回は filter_horizontal
の変更は行いませんが、モデルに ManyToManyField
を持たせるような場合、filter_horizontal
にそのフィールドを指定して選択式でフィールドの設定を行えるようにしてやることでユーザー管理の利便性が上がります。
今回はフィールドを指定するクラス変数のみに焦点を当てて解説していますが、他にも管理画面で使用するテンプレートなどをクラス変数の定義によって指定することも可能です
例えば add_form_template
を定義することによりユーザー追加フォーム表示時のテンプレートを変更するようなことも可能です
他にどのような指定を行うことができるのかについては UserAdmin
クラスの定義をご確認いただければと思います
削除したフィールドを利用しないように実装
UserAdmin
の定義をご覧いただければ分かる通り、各クラス変数において CustomUser
に存在しない下記のフィールドが指定されています。
username
first_name
last_name
is_active
date_joined
現状の CustomUserAdmin
は UserAdmin
を継承するのみで作成しているため、UserAdmin
同様に、CustomUserAdmin
でも上記のフィールドの表示や上記のフィールドの入力受付が行われるようになっていることになります。
そのため、管理画面で CustomUser
を管理できるようにするには、CustomUserAdmin
で上記のフィールドを指定しないように CustomUserAdmin
を実装する必要があります。
やり方は単純で、先ほど示した UserAdmin
の各クラス変数の定義を CustomUserAdmin
のクラス変数として定義し、さらにそのクラス変数に指定する値やタプル等から上記で挙げたフィールドの削除を行います。
CustomUserAdmin
のクラス変数の定義が優先して使用されるため、これによって上記のフィールドが管理画面作成時に利用されないようになります。
具体的な手順としては、まず、CustomUserAdmin
に対し、UserAdmin
でフィールドの指定を行なっている各クラス変数の定義をコピペしてきます。そうすると、admin.py
は下記のようになると思います。
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
class CustomUserAdmin(UserAdmin):
fieldsets = (
(None, {"fields": ("username", "password")}),
(_("Personal info"), {"fields": ("first_name", "last_name", "email")}),
(
_("Permissions"),
{
"fields": (
"is_active",
"is_staff",
"is_superuser",
"groups",
"user_permissions",
),
},
),
(_("Important dates"), {"fields": ("last_login", "date_joined")}),
)
add_fieldsets = (
(
None,
{
"classes": ("wide",),
"fields": ("username", "password1", "password2"),
},
),
)
list_display = ("username", "email", "first_name", "last_name", "is_staff")
list_filter = ("is_staff", "is_superuser", "is_active", "groups")
search_fields = ("username", "first_name", "last_name", "email")
ordering = ("username",)
CustomUser = get_user_model()
admin.site.register(CustomUser)
さらに、上記の各クラス変数において、CustomUser
に存在しないフィールドを削除 or 他のフィールドへの置き換えを行います。
とりあえず例外が発生しないようにするのであれば、admin.py
を下記のように変更してやれば良いです。
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from django.utils.translation import gettext_lazy as _
class CustomUserAdmin(UserAdmin):
fieldsets = (
(None, {"fields": ("email", "password")}),
(
_("Permissions"),
{
"fields": (
"is_staff",
"is_superuser",
"groups",
"user_permissions",
),
},
),
(_("Important dates"), {"fields": ("last_login",)}),
)
add_fieldsets = (
(
None,
{
"classes": ("wide",),
"fields": ("email", "password1", "password2"),
},
),
)
list_display = ("email", "is_staff")
list_filter = ("is_staff", "is_superuser", "groups")
search_fields = ("email", "email")
ordering = ("email",)
filter_horizontal = (
"groups",
"user_permissions",
)
CustomUser = get_user_model()
admin.site.register(CustomUser, CustomUserAdmin)
各クラス変数の変更によって管理画面がどのように変化するのかについては、CustomUserAdmin の実装 の冒頭で説明した各クラス変数の説明を参照していただければと思います。
例えばですが、上記のように add_fieldsets
を変更することにより、管理画面でユーザーを追加する際の入力フォームは次の図のように変化します。
このように、add_fieldsets
に指定したフィールドの入力受付が行えるようユーザー追加フォームが変化していることが確認できると思います(最初の入力フィールドが username
ではなく email
に変わっている)。
また、上図のユーザー追加フォームにおいては、パスワードがマスクされて他の人から見られないようになっています。このパスワードのマスクに関しては、前述の通り UserAdmin
を継承することで実現される機能となります。
ただ、ページの冒頭に下記のような文言があり、ここに username
という文言が残っているので気持ち悪いですね…。今回は説明は省略させていただきますが、このようなページの表示文字列等を変更する場合は使用するテンプレートの変更が必要になります。
First, enter a username and password. Then, you’ll be able to edit more user options.
追加したフィールドを利用するように変更
さて、前述のように CustomUserAdmin
を変更することで、管理画面表示時に CustomUser
に存在しないフィールドが利用されないようになったことになります。
ただ、まだ問題点があります。
これは実際にユーザーの追加を行なってみれば分かるのですが、現状の CustomUserAdmin
を利用して管理画面からユーザーの追加を行うと、下記のような例外が発生することになります。
django.db.utils.IntegrityError: NOT NULL constraint failed: login_app_customuser.height
なんとなく、この例外から現象を推測していただけると思うのですが、現状の CustomUserAdmin
ではユーザー追加時に height
、さらには weight
の入力受付が行われないため、これらの設定を行うことができずに上記のような例外が発生してしまうことになります。
もう少し詳しく説明しておくと、現状の CustomUserAdmin
の add_fieldsets
では "email"
・"password1"
・"password2"
のみが指定されているため、ユーザー追加フォームにおいては、この3つのフィールドの入力受付のみが行われるようになっています。
そして、ユーザー追加時には、これらの入力値が CustomUser
のインスタンスに設定され、そのインスタンスの情報がレコードとしてデータベースに保存されるようになっています(実際には password1
と password2
ではなく、password
のフィールドに値が設定されることになります)。
ただし、CustomUser
では User
に比較して height
と weight
のフィールドを追加しており、さらにこれらのフィールドは設定必須項目として扱われるようになっています。
そのため、height
と weight
のフィールドが設定されていないレコードをデータベースに保存しようとすると、設定必須項目が設定されていないことを理由に上記のような例外が発生することになります。
この例外は、ユーザー追加フォームで height
と weight
の入力受付を行うようにすれば解決することができますので、この方法で例外を解決していきたいと思います(他にも height
と weight
を “設定任意項目” に設定して解決するようなこともできます)。
具体的には、ユーザー追加フォームで入力受付を行うフィールドの指定を行う add_fieldsets
に "height"
と "weight"
の指定を追加してやれば良いです。
また、add_fieldsets
に対してだけでなく、height
と weight
のような CustomUser
に独自に追加したフィールドを他のクラス変数に指定することもできます。そして、これによって管理画面でのユーザー管理の利便性を向上させることができます。
例えば下記のように admin.py
を変更してやれば、ユーザーの追加フォームや編集フォームに height
と weight
の入力受付が行われるようになり、ユーザー一覧リスト等にも height
と weight
が表示されるようになります。
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import gettext_lazy as _
class CustomUserAdmin(UserAdmin):
fieldsets = (
(None, {"fields": ("email", "password")}),
(_("Personal info"), {"fields": ("height", "weight")}),
(
_("Permissions"),
{
"fields": (
"is_staff",
"is_superuser",
"groups",
"user_permissions",
),
},
),
(_("Important dates"), {"fields": ("last_login",)}),
)
add_fieldsets = (
(
None,
{
"classes": ("wide",),
"fields": ("email", "height", "weight", "password1", "password2"),
},
),
)
list_display = ("email", "height", "weight", "is_staff")
list_filter = ("is_staff", "is_superuser", "groups")
search_fields = ("email", "email")
ordering = ("height",)
filter_horizontal = (
"groups",
"user_permissions",
)
CustomUser = get_user_model()
admin.site.register(CustomUser, CustomUserAdmin)
例えば、上記の CustomUserAdmin
を利用して表示されるユーザー一覧リストは次の図のようになります。
height
と weight
が表示されていることが確認できると思いますし、ordering = ("height",)
としているため、height
に対して昇順にユーザーが並んで表示されていることも確認できると思います。
UserAdmin
のサブクラス実装時のポイント
こんな感じで、管理画面でカスタムユーザーを管理するためには、作成したカスタムユーザーに合わせて UserAdmin
のサブクラスの実装を行うことが必要になります。
重要なのは、ここまで説明してきたように、カスタムユーザーの持つフィールドに合わせて管理画面で利用するフィールドを設定することになります。
ここが上手く実現できていないとユーザー管理画面で例外が発生し、上手くユーザーを管理することができなくなるので注意してください。
特に下記の2点については最低限実現できるように、UserAdmin
のサブクラスを実装するようにしてください。
- カスタムユーザーが持たないフィールドはユーザー管理画面からも利用しない
- カスタムユーザーに設定必須のフィールドはユーザー管理画面から設定できるようにする
カスタムユーザーの管理画面の実装例
以上が UserAdmin
のサブクラスの実装方法の解説になります。
最後に、ここまでの復習の意味を込めて、カスタムユーザーを管理画面で管理するための手順および実装例をまとめて示しておきたいと思います。
特にここまでは admin.py
に焦点を当てて解説をしてきましたが、ここでは他のファイルの変更例も含めてカスタムユーザーを管理画面で管理するために最低限必要な実装を紹介していきます。
ただし、ここでは詳細な説明は省略させていただきますので、特にカスタムユーザーの作り方やアプリでのカスタムユーザーの利用の仕方については下記のページを必要に応じて参考にしていただければと思います。
【Django】カスタムユーザー(独自のユーザー)の作り方【AbstractUser編】 【Django】カスタムユーザー(独自のユーザー)の作り方【AbstractBaseUser編】スポンサーリンク
プロジェクトとアプリの作成
では、まずはプロジェクトとアプリを作成していきたいと思います。
プロジェクト名は my_project
、アプリ名は accounts
にしたいと思います。
最初に、下記コマンドを実行してプロジェクト my_project
を作成します。
% django-admin startproject my_project
続いて、上記コマンドで作成される my_project
フォルダの中に移動し、さらに startapp
を実行してアプリ accounts
を作成します。
% cd my_project % python manage.py startapp accounts
次に、my_project
フォルダの中にある settings.py
内の INSTALLED_APPS
を下記のように変更し、プロジェクトに対してアプリを登録します。
# Application definition
INSTALLED_APPS = [
'accounts', # 追加
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
カスタムユーザーの作成
続いてカスタムユーザーを作成していきたいと思います。
今回は、カスタムユーザーとして UserAdmin のサブクラスの実装 で示した CustomUser
をそのまま利用したいと思います。
ということで、accounts
フォルダの中にある models.py
を開き、下記のように変更してください。
from django.db import models
from django.contrib import auth
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
from django.core.mail import send_mail
from django.contrib.auth.hashers import make_password
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import PermissionsMixin
class UserManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
"""
Create and save a user with the given email and password.
"""
if not email:
raise ValueError("The given email must be set")
email = self.normalize_email(email)
# Lookup the real model class from the global app registry so this
# manager method can be used in migrations. This is fine because
# managers are by definition working on the real model.
user = self.model(email=email, **extra_fields)
user.password = make_password(password)
user.save(using=self._db)
return user
def create_user(self, email=None, password=None, **extra_fields):
extra_fields.setdefault("is_staff", False)
extra_fields.setdefault("is_superuser", False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email=None, 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(email, password, **extra_fields)
def with_perm(
self, perm, is_active=True, include_superusers=True, backend=None, obj=None
):
if backend is None:
backends = auth._get_backends(return_tuples=True)
if len(backends) == 1:
backend, _ = backends[0]
else:
raise ValueError(
"You have multiple authentication backends configured and "
"therefore must provide the `backend` argument."
)
elif not isinstance(backend, str):
raise TypeError(
"backend must be a dotted import path string (got %r)." % backend
)
else:
backend = auth.load_backend(backend)
if hasattr(backend, "with_perm"):
return backend.with_perm(
perm,
is_active=is_active,
include_superusers=include_superusers,
obj=obj,
)
return self.none()
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_("email address"), unique=True)
is_staff = models.BooleanField(
_("staff status"),
default=False,
help_text=_("Designates whether the user can log into this admin site."),
)
height = models.FloatField()
weight = models.FloatField()
objects = UserManager()
EMAIL_FIELD = "email"
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["height", "weight"]
class Meta:
verbose_name = _("user")
verbose_name_plural = _("users")
#abstract = True
def clean(self):
super().clean()
self.email = self.__class__.objects.normalize_email(self.email)
def email_user(self, subject, message, from_email=None, **kwargs):
"""Send an email to this user."""
send_mail(subject, message, from_email, [self.email], **kwargs)
AUTH_USER_MODEL
の設定
カスタムユーザーが作成できましたので、次はプロジェクトで認証に利用するモデルを先ほど作成した CustomUser
に設定していきます。
そのために、settings.py
の最後に下記を追記します。
AUTH_USER_MODEL = 'accounts.CustomUser'
これにより、アプリ内での認証や管理画面での認証に CustomUser
が利用されるようになります。
スポンサーリンク
マイグレーションの実行
続いてマイグレーションを実行しましょう!
startproject
で作成された my_project
フォルダ内で下記の2つのコマンドを実行してみてください。おそらくエラーが発生することなく正常にマイグレーションが実行できるはずです。
% python manage.py makemigrations % python manage.py migrate
このマイグレーションによってデータベースに accounts.customuser
というテーブルが作成されることになります。
スーパーユーザーの追加
ここから本題の管理画面に関する変更を行なっていくのですが、管理画面にログインするためにはスーパーユーザーが必要です。
ということで、まずはスーパーユーザーを追加するために、startproject
で作成された my_project
フォルダ内で下記コマンドを実行してみてください。
% python manage.py createsuperuser
上記コマンドを実行すれば、作成するスーパーユーザーのメールアドレス・身長・体重・パスワード(確認用も含めて2回)の入力受付が順次行われますので作成したいスーパーユーザーに合わせて入力を行なっていってください。
% python manage.py createsuperuser Email address: hanako@yamada.jp Height: 167.2 Weight: 56.2 Password: Password (again): Superuser created successfully.
この入力によって、スーパーユーザーが作成されるはずです。
管理画面の設定後、このスーパーユーザーで管理画面へのログインを行うため、上記で入力したメールアドレスとパスワードはメモしておいてください。
管理画面の設定
最後に管理画面の設定を行ない、models.py
に作成したカスタムユーザーに合わせたユーザー管理画面を実現していきます。
この設定に関しても、UserAdmin のサブクラスの実装 で紹介した内容と同じ設定を行うことにしたいと思います。
要は、UserAdmin
のサブクラスを定義し、そのクラスを CustomUser
の持たないフィールドを利用しないように、さらに CustomUser
に追加したフィールドを利用しないように実装していきます。
これは、結局は accounts
フォルダの下の admin.py
を下記のように変更することで実現できます。
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import gettext_lazy as _
class CustomUserAdmin(UserAdmin):
fieldsets = (
(None, {"fields": ("email", "password")}),
(_("Personal info"), {"fields": ("height", "weight")}),
(
_("Permissions"),
{
"fields": (
"is_staff",
"is_superuser",
"groups",
"user_permissions",
),
},
),
(_("Important dates"), {"fields": ("last_login",)}),
)
add_fieldsets = (
(
None,
{
"classes": ("wide",),
"fields": ("email", "height", "weight", "password1", "password2"),
},
),
)
list_display = ("email", "height", "weight", "is_staff")
list_filter = ("is_staff", "is_superuser", "groups")
search_fields = ("email", "email")
ordering = ("height",)
filter_horizontal = (
"groups",
"user_permissions",
)
CustomUser = get_user_model()
admin.site.register(CustomUser, CustomUserAdmin)
スポンサーリンク
動作確認
変更は以上になります。最後に動作確認を行なっておきましょう!
管理画面にアクセスするためには、まずは下記コマンドで Django の開発用ウェブサーバーを起動しておく必要があります。
% python manage.py runserver
Django の開発用ウェブサーバー起動後、ウェブブラウザで下記 URL にアクセスすれば、管理画面へのログインフォームが表示されるはずです。ここには、先ほど作成したスーパーユーザーのメールアドレスとパスワードを入力してください。
http://localhost:8000/admin/
ログインに成功すれば、あとはいつも通りの感覚でユーザーの管理を行なってみてください。
例えば管理画面のトップページにおける Users
リンクをクリックすればユーザー一覧リストが表示されます。まだユーザーは一人だと思いますが、height
や weight
といった CustomUser
独自のフィールドの情報が表示されていることが確認できると思います。
また、ユーザー一覧リスト表示ページにおける右上の ADD USER +
ボタンをクリックすればユーザー追加フォームが表示され、ここでも height
や weight
といった CustomUser
独自のフィールドの入力が可能であることを確認できると思います。
このような動作結果より、admin.py
の変更によってカスタムユーザーに応じた管理画面のカスタマイズを行うことができることを確認していただけるのではないかと思います。
最後に、実際にユーザーを新規追加し、そのユーザーでログインできることを確認しておきましょう!
まずは、上の図で示す追加フォームの各種フォームに入力を行い、ページ下部の SAVE
ボタンをクリックしてください。ユーザーの追加に成功すれば、そのユーザーの編集フォームが表示されることになります。
まず、この編集フォームの先頭部分で、パスワードがしっかり暗号化されていることが確認できるはずです。これは、CustomUserAdmin
を UserAdmin
のサブクラスとして定義したことによる効果となります。
さらに、編集フォームで Staff status
と Superuser status
の両方のチェックを ON に変更し、ページ下部の SAVE
ボタンをクリックしてください。これにより、この追加したユーザーに管理画面での全管理の権限が付与されたことになります。当然管理画面へのログインも可能です。
ということで、ログインの確認を行なっておきましょう!まずページ上部の LOG OUT
リンクをクリックしてログアウトを行い、さらに遷移後のページから Log in again
リンクをクリックしてログインフォームを表示してください。
そして、表示されたログインフォームに、先ほど追加フォームから追加したユーザーのメールアドレスとパスワードを入力し、Log in
ボタンをクリックしてください。おそらく、ログインに成功するはずです。
このログインは、ModelAdmin で User を管理した時の動作 で実際に確認したように、ModelAdmin
では実現できなかったことになります。この点からも、カスタムユーザーを管理する際には ModelAdmin
ではなく UserAdmin
のサブクラスを利用する必要があることを理解していただけると思います。
まとめ
このページでは、Django での管理画面(admin
)でカスタムユーザーを管理する方法について解説しました!
管理画面は基本的にはモデルクラス毎に ModelAdmin
のサブクラスを定義してカスタマイズすることになりますが、カスタムユーザーの場合は ModelAdmin
のサブクラスでは不十分です。パスワードの暗号化等が行われません。
そのため、カスタムユーザーの管理画面に関しては UserAdmin
のサブクラスを定義してカスタマイズする必要があります。
ただし、あくまでも UserAdmin
は User
を管理するためのクラスであり、そのまま使用すると User
の持つフィールドに合わせて管理画面が表示されることになるので注意してください。User
の持つフィールドをカスタムユーザーが持たないような場合、例外が発生する恐れがあります。
管理画面を利用することで、管理者専用のユーザーの管理なども行うことができるようになるため、ぜひ今回説明した内容は覚えておいてください!
[…] だえうホームページ 【Django】ユーザー管理画面(admin)のカスタマイズ このページでは、Django […]