このページでは、Django での「カスタムユーザー」の作り方について解説していきます。
Contents
カスタムユーザーとは
カスタムユーザーとは、要はアプリ開発者が独自で作成する「ユーザー管理モデル(ユーザーを管理するモデル)」のことになります。
下記のページで Django でのログインの実現の仕方について解説していますが、ログインを実現するためにはユーザー管理モデルが必要になります。
【Django】ログイン機能の実現方法(関数ベースビュー編) 【Django】ログイン機能の実現方法(クラスベースビュー編)上記のページでは、このユーザー管理モデルとして、Django に標準で用意されている User
を利用しました。
Django に標準で用意されているため、この User
を利用することで簡単にユーザーを管理することができるようになるのですが、この User
の利用は、実は Django の公式で非推奨とされています。
そのため、Django でウェブアプリを開発していく際には、ユーザー管理モデルとして User
の代わりとなるカスタムユーザー(独自のユーザー)を作成し、そのモデルを利用してユーザーを管理していく必要があります。
このページでは、このカスタムユーザーモデルの作り方について解説していきます。
もちろんお試しでログイン機能を実現したい場合などは User
を利用しても良いです
ただ、実際に他のユーザーに利用してもらうようなアプリを開発するような場合は、User
ではなくカスタムユーザーを利用した方が良いです
カスタムユーザーを利用する主な理由(User
の利用が非推奨である理由)は下記となります
- ユーザー管理モデルはアプリに応じて変更したくなることが多いが
User
は変更できない - 後から
User
の代わりにカスタムユーザーを利用しようと思ってもマイグレーション時にエラーが出て大変
カスタムユーザー作成時に必要になる手順
最初に、カスタムユーザーを作成し、さらにウェブアプリでカスタムユーザーを利用していくために必要になる手順の全体像を示しておきます。
まずは、カスタムユーザーをモデルとして定義して作成する必要があります。これは、クラス(モデル)の継承を利用することで簡単に実現することができます。
このページでは、AbstractUser
を継承することでカスタムユーザーを作成していきます。
ただし、単に AbstractUser
を継承しただけだと User
と同等のモデルしか作成することができません。アプリに応じてユーザーで管理する情報やユーザーの動作を変更したい場合、フィールドやメソッドの追加等のカスタマイズを行う必要があります。
さらに、このカスタムユーザーを用いてログイン等に必要な「認証」を実現していく必要があります。これは単に、アプリで認証時に使用するモデルとして作成したカスタムユーザーを設定してやれば良いのみになります。
また、Django では管理画面(admin
画面)からユーザーの管理を行うことができます。管理対象が User
からカスタムユーザーに変わるため、管理画面でカスタムユーザーを管理できるように設定する必要があります。
あとは、フォームやビュー作成時に、必要に応じてカスタムユーザーを利用するようにしてやれば良いだけです。
ということで、カスタムユーザーを作成し、そしてそれをアプリで使用していくためには、大きく分けて下記の4つの手順が必要になることになります。ここからは、下記の4つの手順それぞれについて解説を行なっていきます。
フォームやビュー作成時のカスタムユーザーの利用については手順としての解説は省略しますが、最後の カスタムユーザーを利用するアプリの開発例 で具体的な実装例を紹介したいと思います。
スポンサーリンク
カスタムユーザーを定義する
では、まずはカスタムユーザーを定義する手順について解説していきます。
カスタムユーザーの定義の仕方
まず前提として、Django ではユーザー管理モデルを利用して認証等が実現されます。つまり、自身でユーザー管理モデルを作成する場合には、そのモデルで認証等が実現できる様に作成していく必要があります。こういった背景があるので、ユーザー管理モデルをゼロから自力で作成するのは非常に大変です。
そのため、カスタムユーザーは Django に標準で用意されているモデル(クラス)を継承し、それをカスタマイズしていくことで作成していくのが一般的な方法となります。
具体的には、カスタムユーザーは下記のようなモデル(クラス)を継承することで作成することができます。
AbstractUser
を継承してカスタムユーザーを作るAbstractBaseUser
とPermissionsMixin
を継承してカスタムユーザーを作る
AbstractUser
を継承してカスタムユーザーモデルを定義する
User
および、上記で挙げた3つのモデルには下の図のような継承関係があります。吹き出し内で簡単に各モデルで実現していること、さらに吹き出しの括弧内には各モデルで定義されるフィールドの例を示しています。
上の図にも記載の通り、AbstractUser
にはユーザーを管理するための一般的なフィールドやメソッドが用意されていますので、下の図のように、AbstractUser
を継承したモデルを定義するだけでユーザーを管理可能なモデルを作成することができます(AbstractUser
は AbstractBaseUser
と PermissionsMixin
を継承しているので、AbstractUser
を継承したモデルは権限管理や認証を行うことも可能です)。
また、上の図で示すように、実は User
も AbstractUser
を継承して作成されています。User
の具体的な定義は下記のようになります(Django 4.0.5 時点の定義になります)。
class User(AbstractUser):
"""
Users within the Django authentication system are represented by this
model.
Username and password are required. Other fields are optional.
"""
class Meta(AbstractUser.Meta):
swappable = "AUTH_USER_MODEL"
ちょっと swappable
の意味合いを私も理解していないのですが、上記を見ていただければ分かる様に、ほぼ User
は AbstractUser
を継承するのみで作成されていることが確認できると思います。
これはつまり、AbstractUser
を継承さえすれば User
同等のカスタムユーザーを作成可能であることを意味します。
そのため、User
同等のカスタムユーザー(User
と同じ機能を持つモデル)に関しては、AbstractUser
を継承するのみで作成することが可能です。
また、User
の持たないフィールドやメソッドをカスタムユーザーに持たせたいような場合も、ひとまず AbstractUser
を継承してカスタムユーザーを定義し、その後にカスタムユーザーに必要なフィールドやメソッド(User
に存在しないフィールドやメソッド)を追加していくのが一般的なカスタムユーザーの作成方法となります。
ということで、AbstractUser
を継承してカスタムユーザーを作成する場合、まずは models.py
を下記のように記述してカスタムユーザーを定義してやれば良いです(以降、作成するカスタムユーザーのモデル名は CustomUser
として解説していきますが、 必要に応じて変更しても問題ないです)。
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
pass
もちろんアプリで使用するユーザー管理モデルが User
と同等で良いのであれば、上記の定義のみでカスタムユーザーの作成は完了となります。
User
同等のモデルをわざわざ作成する必要もない様に感じるかもしれないですが、User
は Django 本体で定義されているモデルなので変更することができません。
いや、正確には変更することはできるのですが、変更すると全アプリに影響を及ぼすことになるため、User
自体を変更することはやめた方が良いです。
それに対し、CustomUser
はウェブアプリ(もしくはプロジェクト)毎に定義するモデルであるため、変更したとしても影響を及ぼすのはウェブアプリ内のみになります。
そのため、開発したいウェブアプリに応じて自由自在に変更することが可能です。
また、冒頭でも述べたように、User
自体を使うことは非推奨とされているため、User
を利用したい場合であっても、上記のように CustomUser
を models.py
に別途定義してやった方が良いです。
スポンサーリンク
AbstractBaseUser
を継承して定義することも可能
ここまで AbstractUser
を継承することを前提に解説してきましたが、AbstractUser
ではなく AbstractBaseUser
および PermissionsMixin
を継承してカスタムユーザーを定義することも可能です。
AbstractUser
を継承すると、当然ながら username
や email
などのユーザーを管理するためのフィールドもカスタムユーザーモデルに継承されることになります(具体的に継承されるフィールドは後述で紹介します)。
しかし、作成したいカスタムユーザーによっては継承されるフィールドが不要となることもあります。例えば、ユーザーの情報として username
が不要なアプリも存在すると思います。
そんな時は、AbstractUser
ではなく AbstractBaseUser
と PermissionsMixin
を継承する方が良いと思います。この場合、認証やグループ・権限管理などの、ユーザー管理を実現する上で最低限必要なフィールドしか継承されません。
最低限必要なフィールドしか継承されないため、不要なフィールドが継承されることなく、後から自分で好きなもののみをフィールドとして持たせることが出来ます(もちろんメソッドも)。
ただ、自由度が高い分、AbstractUser
を継承するときに比べて実装難易度も上がります。
この AbstractBaseUser
と PermissionsMixin
を継承してカスタムユーザーを作成していく手順については、別途下記ページで解説していますので、必要に応じてこちらのページも参考にしていただければと思います。
カスタムユーザーをカスタマイズする
さて、先ほども説明したように、User
同等のカスタムユーザーは AbstractUser
を継承して定義するだけで作成することが出来ます。
ただし、アプリによっては AbstractUser
から継承するフィールドやメソッドのみでは機能的に足りない場合もあるため、ここでフィールドやメソッドの追加等を行う手順について解説していきたいと思います。
AbstractUser
から継承されるフィールド・メソッド
ただ、CustomUser
に対して不足しているフィールドやメソッドの追加を行おうと思っても、CustomUser
の持つフィールドやメソッドが分からないと、何が不足しているか分からないですよね…。
なので、まずは CustomUser
の持つフィールドやメソッド、すなわち AbstractUser
から継承されるフィールドやメソッドについて紹介しておきたいと思います。
AbstractUser
で定義されているフィールドとメソッドには下記の様なものが存在します。CustomUser
は AbstractUser
を継承して作成しているため、CustomUser
もこれらのフィールドとメソッドを持つことになります。
- フィールド
username
:CharField
first_name
:CharField
last_name
:CharField
email
:EmailField
is_staff
:BooleanField
is_active
:BooleanField
date_joined
:DateTimeField
- メソッド
clean
get_full_name
get_short_name
email_user
上記は、あくまでも AbstractUser
で定義されたフィールドとメソッドです。
前述の通り、AbstractUser
自体も AbstractBaseUser
と PermissionsMixin
を継承して作成されているモデルなので、CustomUser
は AbstractBaseUser
や PermissionsMixin
で定義されているフィールドやメソッドも継承することになります。例えば password
や last_login
などの認証用のフィールドや group
や is_superuser
などのグループ・権限管理用のフィールドも継承されます。
ただ、これらのフィールドやメソッドに関しては、認証機能やグループ・権限管理機能をカスタマイズしたいような場合でなければ意識する必要はないため、基本的には上記で挙げたフィールドやメソッドだけを意識し、開発するアプリに不足しているものを追加していけば良いと思います。
また、上記で列挙したメソッドの具体的動作を知りたい方は、是非 AbstractUser
の定義を自身で確認してみてください。
VSCode の場合、クラスの定義は下記ページで紹介している手順で簡単に確認することができます。
【Django】VSCodeでクラスの定義を簡単に確認する方法スポンサーリンク
フィールドの追加
CustomUser
に既に存在するフィールドについては理解していただけたと思いますので、続いてはフィールドの追加の仕方を解説していきたいと思います。
カスタムユーザーに関しても、通常の Python におけるサブクラスと同様にしてカスタマイズすることができます。
具体的には、クラス変数の追加やメソッドの追加、メソッドのオーバーライドなどが可能です。
フィールドの追加方法
フィールドの追加に関しては、クラス変数の追加によって実現することができます。
例えば下記のように CustomUser
にクラス変数 nickname
・height
・weight
を追加すれば、それぞれ文字列型のフィールドとして nickname
が、さらに浮動小数点数型のフィールドとして height
と weight
がカスタムユーザーに追加されることになります。
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
nickname = models.CharField(max_length=100)
height = models.FloatField()
weight = models.FloatField()
入力必須フィールドの設定
上記の通り、フィールドの追加自体は簡単に行うことができるのですが、入力必須のフィールドを追加する場合は注意が必要になります。
フィールドはデフォルトでは blank
オプションが False
で設定されており、入力必須のフィールドとして作成されることになります。
つまり、先ほど追加した nickname
・height
・weight
の3つのフィールドは全て入力必須フィールドとなります。
そのため、先ほど作成した CustomUser
のユーザーを追加する際には nickname
・height
・weight
の3つのフィールドも設定できるようにする必要があるので注意してください。
例えばユーザーを追加する入力フォームにおいて、入力必須のフィールドの値の設定もできるように入力エントリー等を追加する必要があります。
このように、入力フォームから入力を受け付けてユーザーを追加する場合は、自身が作成するフォームで入力必須のフィールドの値を入力できるようにしてやれば良いだけです。
ですが、createsuperuser
コマンドでユーザーを追加する場合は、別途カスタムユーザーの設定を行わない限り、username
・email
・password
しか入力受付が行われないので注意してください。
つまり、前述の CustomUser
のように入力必須フィールドを追加した場合、デフォルトでは createsuperuser
コマンド実行時のユーザー追加時に nickname
・height
・weight
を入力・設定することができず、必ずユーザー追加に失敗することになります。
createsuperuser
コマンドからもユーザーを追加できるようにするためには、createsuperuser
コマンド実行時に入力受付されるフィールドとして nickname
・height
・weight
を設定してやる必要があります。
この設定は、REQUIRED_FILEDS
のクラス変数に入力必須フィールドをリスト形式で指定することで実現できます。
ただし、ここがちょっとややこしいのですが、この REQUIRED_FILEDS
に指定するリストに USENAME_FIELD
と password
のフィールドが含まれるとエラーになるので注意してください。この USERNAME_FIELD
と password
のフィールドは REQUIRED_FILEDS
に指定するリストに含めなくても自動的に createsuperuser
実行時に入力受付が行われるようになっています。
また、USERNAME_FIELD
とは、ユーザーを一意に識別するためのフィールドであり、デフォルトでは username
が設定されています。例えば、ユーザーを一意に識別するためのフィールドを username
ではなく email
(メールアドレス)にしたい場合は USERNAME_FILED
の設定を別途行う必要があります。
ですが、今回は username
でユーザーを一意に識別することを前提に解説していきたいと思いますので、USENAME_FIELD
の設定は行いません。
上記の解説を踏まえると、CustomUser
モデルのクラス変数で下記のように REQUIRED_FILEDS
を設定することで、createsuperuser
実行時に username
・email
・nickname
・height
・weight
・password
の入力受付が行われるようになり、上手くユーザーを作成することができるようになります。
class CustomUser(AbstractUser):
nickname = models.CharField(max_length=100)
height = models.FloatField()
weight = models.FloatField()
# usernameとpasswordの指定は不要
REQUIRED_FIELDS = ["email", "nickname", "height", "weight"]
ちなみに、REQUIRED_FILEDS
のデフォルト設定は ["email"]
となっています。こういった各種変数のデフォルト設定は AbstractUser
の定義から確認することができます。
(参考)フィールドの上書き方法
また、フィールドは追加だけではなくて削除する様なことも可能ではあります。
例えば、date_joined
というフィールドが不要であれば、下記の様に date_joined
を None
で上書きしてやれば、CustomUser
から date_joined
フィールドを削除することも可能です。
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
date_joined = None
同様にクラス変数を上書きしてやることで、AbstractUser から継承されるフィールド・メソッド で挙げたフィールドのオプション等を変更することも可能です。例えば email
は入力が必須ではないフィールドなのですが、次のように email
を上書きしてやれば、email
を入力必須のフィールドに変更することも可能です。
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
email = models.EmailField(blank=False)
ただ、こういったフィールドの上書きは他のサイト等で紹介されていないやり方になりますし、AbstractUser
ではなく AbstractBaseUser
を継承するようにすれば、そもそも不要なフィールドを持たないようにカスタムユーザーを作成することが可能であり、おそらくこちらのやり方の方が推奨されているのではないかと思います。
前述の通り、AbstractBaseUser
を継承してカスタムユーザーを作成する手順については別途下記ページで解説していますので、不要なフィールドを持たないカスタムユーザーを作成したいような場合はこちらを参考にしていただければと思います。
メソッドの追加
また、メソッドの追加も可能で、これによりフィールドの情報を加工して取得する様なことが可能になります。
例えば下記の様にメソッドを CustomUser
に追加すれば、CustomUser
のインスタンスに get_bmi
を実行させることで、そのインスタンスのユーザーの BMI 値を取得することができる様になります。
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
height = models.FloatField()
weight = models.FloatField()
def get_bmi(self):
"""Return the bmi for the user."""
return self.weight / ((self.height / 100) * (self.height / 100))
メソッドのオーバーライド
同様に、メソッドのオーバーライドも可能で、これにより AbstractUser
で定義されたメソッドの動作を上書きすることが可能です。
このオーバーライドは、AbstractUser から継承されるフィールド・メソッド で挙げたメソッドと同じ名前のメソッドを CustomUser
に追加することで実現できます。
例えば、AbstractUser
で定義されている get_short_name
は first_name
フィールドの文字列を単に返却するメソッドになりますが、下記の様にメソッドを CustomUser
に追加すれば get_short_name
がオーバーライドされ、CustomUser
に新たに追加した nickname
フィールドの文字列を返却するように動作を上書きすることができます。
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
nickname = models.CharField(max_length=100)
def get_short_name(self):
"""Return the short name for the user."""
return self.nickname
こんな感じで、フィールドの追加やメソッドの追加・オーバーライドを行なっていくことで、アプリに応じたカスタムユーザーを作成していくことができます。
スポンサーリンク
認証にカスタムユーザーを利用する
続いて、認証に利用するユーザー管理モデルを先ほど作成した CustomUser
に設定していきたいと思います。
Django で開発するアプリにおいては、デフォルト設定では認証時に User
モデルを使用することが前提となっています。
ですので、せっかくカスタムユーザーを作成したとしても、デフォルト設定のままだと認証に User
モデルが利用されることになって意味がありません。
そのため、カスタムユーザーを定義した際には、認証に使用するユーザー管理モデルとしてカスタムユーザーを設定してやる必要があります。
この、認証で使用するユーザー管理モデルの設定は settings.py
で行うことができます。
より具体的には、下記のように settings.py
に AUTH_USER_MODEL
の定義を加えることで、アプリ内で利用するユーザー管理モデルを models.py
で定義したカスタムユーザーに設定することができます。
AUTH_USER_MODEL = 'アプリ名.カスタムユーザーのModel名'
例えば アプリ名
(python manage.py startapp
で作成するアプリの名前) が login_app
、さらに models.py
で定義した カスタムユーザーのModel名
が CustomUser
であれば、settings.py
には下記を追記することになります。
AUTH_USER_MODEL = 'login_app.CustomUser'
上記の設定を行うことで、認証時に使用するユーザー管理モデルとして カスタムユーザーを定義する で定義した CustomUser
が使用されるようになり、マイグレーション実行時にデータベースに login_app_customuser
というテーブルが作成されることになります(Django ではモデル毎にテーブルが作成される)。
また、AUTH_USER_MODEL
を変更せずにマイグレーションを実行した場合、カスタムユーザーを定義 で定義したモデルのテーブルだけでなく、AUTH_USER_MODEL
にデフォルトで設定されている User
のテーブルまで作成されることになります。
この際には、おそらく下記のようなエラーが発生することになるので注意してください。
% python manage.py makemigrations auth.User.groups: (fields.E304) Reverse accessor for 'auth.User.groups' clashes with reverse accessor for 'login_app.CustomUser.groups'. HINT: Add or change a related_name argument to the definition for 'auth.User.groups' or 'login_app.CustomUser.groups'.
どうやら AbstractUser
を継承して作成したカスタムユーザーモデルと User
とは共存できないようになっており、両方のテーブルが作成されると上記のエラーが発生するようです。そのため、どちらか一方のモデルのテーブルは作成されないようにする必要があります。
このカスタムユーザーと User
の両方のテーブルが作成されてしまう原因は、カスタムユーザーを定義したにも関わらず AUTH_USER_MODEL
に User
が設定されている点にありますので、AUTH_USER_MODEL
に「models.py
に定義したカスタムユーザー」を設定することで正常にマイグレーションを行うことができるようになります。これは、認証に使用するユーザー管理モデルが User
ではなくなるため、マイグレーション時に User
のテーブルが作成されなくなるからです。
逆に、ユーザー管理モデルを User
に戻したい場合は、models.py
にカスタムユーザーの定義が存在すると上記のエラーが発生することになるため、models.py
からカスタムユーザーの定義を消す or コメントアウトする必要があります。
おそらく別の手段でもエラーは回避できると思うのですが、おそらく上記のやり方がエラー回避方法として一番簡単だと思います
管理画面でカスタムユーザーを利用する
次は、管理画面関連の設定について解説していきます。
管理するユーザーをカスタムユーザーに設定する
ここまで紹介してきたような models.py
と settings.py
の変更によりカスタムユーザーが作成され、さらにウェブアプリ内で認証を行う際にカスタムユーザーが使用されるようになりました。
ウェブアプリを動作させるだけであれば、ここまでの変更内容のみで上手くいくのではないかと思います。
ただし、現状のままだと、下の図のように管理画面(admin
画面)でユーザーに関するセクションが表示されず、管理画面でのユーザー管理が出来ない状態になっています。そのため、続いて管理画面でカスタムユーザーモデルのユーザーの管理を行うための手順を解説していきます。
といっても、管理画面でカスタムユーザーの管理を行うための手順は単純で、単にアプリフォルダ内にある admin.py
を下記のように変更すれば良いだけになります。
from django.contrib import admin
from django.contrib.auth import get_user_model
CustomUser = get_user_model()
admin.site.register(CustomUser)
get_user_model
は、settings.py
で AUTH_USER_MODEL
に指定されているモデルを取得する関数になります。認証にカスタムユーザーを利用する で解説した通りに settings.py
を変更した場合、この返却値として models.py
で定義した CustomUser
モデルが取得されることになります。
さらに、get_user_model
関数の返却値を引数に指定して admin.site.register
を実行すれば、管理画面で管理するユーザーとして AUTH_USER_MODEL
に指定されているモデル、すなわち models.py
で定義した CustomUser
が指定されることになります。
そして、これによって、下の図のように管理画面にユーザーを管理するセクションが表示されるようになり、カスタムユーザーを管理画面で管理することができるようになります。
また、上記のスクリプトのように、認証に利用しているモデルを指定する際には、直接モデル名を指定するのではなく、get_user_model
関数を使用するように心がけると良いと思います。
直接モデル名を指定していると、AUTH_USER_MODEL
を変更した際に、モデル名を指定している箇所全ての変更を行う必要があります。
ですが、get_user_model
関数で取得したモデルを指定するようにしておけば、AUTH_USER_MODEL
を変更した際に get_user_model
関数の返却値も自動的に変更されることになり、モデルの指定箇所の変更が不要になって手間が減ります(上記の場合は admin.site.register
の引数の変更が不要)。
ビューやフォーム等でユーザーのモデルを指定する場合も、直接モデルを指定するのではなく、get_user_model
関数の返却値を指定するようにしてやった方が、AUTH_USER_MODEL
変更時の手間が減り、変更しやすいソースコードに仕立てることができて良いと思います。
スポンサーリンク
管理画面をカスタマイズする
ただし、先ほど示した admin.py
では、管理画面からカスタムユーザーを管理するための必要最低限の設定しか行われません。
実際の画面は後述の カスタムユーザーを利用するアプリの開発例 でアプリを実際に作りながら紹介しますが、先ほど示したスクリプトのままだとユーザー追加時にパスワードがそのまま表示されてしまいますし、ユーザー追加時に入力不要なフィールドまで入力受付が行われて冗長です。
こういった問題点は、管理画面(特にユーザー管理を行う画面)をカスタマイズすることで解決することが可能です。
この管理画面(ユーザー管理画面)のカスタマイズ方法については下記ページで解説していますので、必要に応じて是非このページを読み終わった後にでも読んでみていただければと思います。
【Django】管理画面でカスタムユーザーを管理する(UserAdmin)カスタムユーザーを利用するアプリの開発例
以上が、カスタムユーザー作成およびアプリをカスタムユーザーを利用して動作させるために必要な手順となります。
最後に、ここまで解説してきた内容を踏まえながら、カスタムユーザーを利用する簡単なアプリを作成し、動作確認を行なっていきたいと思います。
プロジェクトとアプリの作成
まずは、いつも通りプロジェクトとアプリを作成していきます。
最初に、下記コマンドを実行してプロジェクト login_project
を作成します。
% django-admin startproject login_project
続いて、上記コマンドで作成される login_project
フォルダの中に移動し、さらに startapp
を実行してアプリ login_app
を作成します。
% cd login_project % python manage.py startapp login_app
次に、login_project
フォルダの中にある settings.py
内の INSTALLED_APPS
を下記のように変更し、プロジェクトに対してアプリを登録します。
# Application definition
INSTALLED_APPS = [
'login_app', # 追加
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
スポンサーリンク
カスタムユーザーの作成
続いて、カスタムユーザーを定義する と カスタムユーザーをカスタマイズする の内容を踏まえてカスタムユーザーを作成していきたいと思います。
今回は、User
に対して nickname
・height
・weight
の3つのフィールドを追加したカスタムユーザーを作成していきます。さらに、BMI を返却する get_bmi
メソッドの追加と、get_short_name
メソッドのオーバーライドを行なっていきたいと思います。
そのために、login_app
フォルダの中にある models.py
を開き、下記のように変更します。
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
nickname = models.CharField(max_length=100)
height = models.FloatField()
weight = models.FloatField()
def get_bmi(self):
"""Return the bmi for the user."""
return self.weight / ((self.height / 100) * (self.height / 100))
def get_short_name(self):
"""Return the short name for the user."""
return self.nickname
カスタムユーザーを定義する や カスタムユーザーをカスタマイズする で解説したように、AbstractUser
を継承したモデル CustomUser
は User
とほぼ同等のモデルとなります。さらに CustomUser
に対してフィールドやメソッドを追加することで、User
が持っていないフィールドやメソッドを CustomUser
に持たせることができます。
また、get_short_name
に関しては User
も持っているメソッドになりますが、オーバーライドを行なっているため、CustomUser
の get_short_name
は User
の get_short_name
から動作が変更されていることになります。
AUTH_USER_MODEL
の設定
通常であれば、models.py
でモデルを定義した後はマイグレーションを行うのですが、認証にカスタムユーザーを利用する で解説した通り、カスタムユーザーを定義しただけではマイグレーションを行うとエラーが発生します。
そのため、マイグレーションの前に settings.py
を変更して AUTH_USER_MODEL
の設定を行なっていきます。
具体的には、settings.py
の最後に下記を追記し、アプリ内で認証時に利用するユーザー管理モデルとして先ほど作成した CustomUser
を設定します。
AUTH_USER_MODEL = 'login_app.CustomUser'
マイグレーションの実行
続いてマイグレーションを実行していきましょう!
startproject
で作成された login_project
フォルダ内で下記の2つのコマンドを実行してみてください。おそらくエラーが発生することなく正常にマイグレーションが実行できるはずです。
% python manage.py makemigrations % python manage.py migrate
このマイグレーションによって login_app.customuser
というテーブルが作成されることになります。
そして、この login_app.customuser
テーブルには、CustomUser
に追加した nickname
・height
・weight
の3つの列が存在しているはずです(下の図は VSCode の SQLite Viewer プラグインで login_app.customuser
テーブルを表示した結果となります)。
あとは、ビュー等からレコードの保存や取得等を行うことで、カスタムユーザーの管理を実現できることになります。
スポンサーリンク
スーパーユーザーの追加
ビューの作成などを行う前に、次は管理画面でカスタムユーザーを管理できるように設定していきたいと思います。
この管理画面にアクセスするためにはスーパーユーザーが必要ですので、まずはスーパーユーザーを追加していきましょう!
このスーパーユーザーの追加を行うために、startproject
で作成された login_project
フォルダ内で下記コマンドを実行してみてください。
% python manage.py createsuperuser
おそらく、ここまで紹介してきた変更だけでは上記実行時に、次のようなエラーが発生するはずです。
% python manage.py createsuperuser Username: YamadaHanako Email address: hanako@yamada.jp Password: Password (again): Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/backends/utils.py", line 89, in _execute return self.cursor.execute(sql, params) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/backends/sqlite3/base.py", line 477, in execute return Database.Cursor.execute(self, query, params) sqlite3.IntegrityError: NOT NULL constraint failed: login_app_customuser.height 〜略〜 django.db.utils.IntegrityError: NOT NULL constraint failed: login_app_customuser.height
このエラーが発生しているのは、createsuperuser
を実行して CustomUser
のユーザーを追加する際に、入力必須となっているフィールド(nickname
・height
・weight
)が入力されていないためです。
そもそも createsuperuser
実行時にこれらのフィールドの入力受付が行われていないので入力することは不可能です…。
ですので、createsuperuser
実行時にこれらのフィールドの入力受付が行われるよう修正する必要があります。そして、この修正は、入力必須フィールドの設定 で解説したように REQUIRED_FIELDS
の設定を追加することにより実現できます。
ということで、下記のように models.py
の CustomUser
を変更してみましょう。
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
nickname = models.CharField(max_length=100)
height = models.FloatField()
weight = models.FloatField()
# ↓追加
REQUIRED_FIELDS = ["email", "nickname", "height", "weight"]
def get_bmi(self):
"""Return the bmi for the user."""
return self.weight / ((self.height / 100) * (self.height / 100))
def get_short_name(self):
"""Return the short name for the user."""
return self.nickname
さらに、先ほど同様に下記コマンドを実行してスーパーユーザーを追加してみてください。REQUIRED_FIELDS
の設定を追記したことで、今度は CustomUser
における入力必須フィールドである nickname
・height
・weight
の入力が行うことができ、スーパーユーザーの追加にも成功するはずです。
% python manage.py createsuperuser Username: YamadaHanako Email address: hanako@yamada.jp Nickname: Hana Height: 170 Weight: 50 Password: Password (again): Superuser created successfully.
このように、カスタムユーザーを作成してフィールドを追加した場合、ユーザー追加時の処理等も追加したフィールドを考慮して動作するように設定する必要があるので注意してください(特に入力必須フィールドの場合は注意が必要です)。
管理画面の設定
次は、管理画面でカスタムユーザーを管理できるように設定を行なっていきます。
まずは現状を把握するために管理画面にアクセスしてみましょう!
管理画面にアクセスする際には、Django の開発用ウェブサーバーを起動しておく必要がありますので、最初に下記コマンドを実行しておいてください。
% python manage.py runserver
コマンド実行後、次は下記 URL をウェブブラウザで開くと、管理画面へのログイン画面が表示されるはずです。
http://localhost:8000/admin/
このログイン画面では、先ほど作成したスーパーユーザーのユーザー名とパスワードを指定して Log in
ボタンを押してください。
ログインに成功した際には、下の図のような管理画面が表示されるはずです。
上の図を見ていただければわかる通り、現状では管理画面で行えるのはグループの管理のみであり、ユーザーの管理が行えない状態になっています。
次は、管理画面からユーザーの管理が行えるように管理画面のカスタマイズを行なっていきます。
管理画面でカスタムユーザーを利用する で説明したように、admin.py
で admin.site.register
を実行してカスタムユーザーを登録してやることにより、管理画面からユーザーの管理を行うことができるようになります。
ということで、login_app
フォルダの下にある admin.py
を下記のように変更しましょう!
from django.contrib import admin
from django.contrib.auth import get_user_model
CustomUser = get_user_model()
admin.site.register(CustomUser)
変更後に、再度下記 URL をウェブブラウザで開いてみてください(必要に Django 開発用ウェブサーバーを起動してください)。
http://localhost:8000/admin/
今度は LOGIN_APP
というセクションが現れ、Users
というリンクが表示されるようになっているはずです。
そのリンクをクリックすれば、下の図のように「ユーザー一覧リスト」が表示されます。
ユーザー一覧リストからユーザー名をクリックすれば、下の図のように「ユーザー詳細フォーム」が表示され、さらにここでユーザーの情報の変更も可能です。
また、ユーザー一覧リストの右上にある ADD USER +
のボタンをクリックすれば、下の図のような「ユーザ作成フォーム」が表示され、必要な入力を行なって画面下の SAVE
ボタンをクリックすることでユーザーの追加を行うことができます(太字部分が入力必須項目となります)。
ユーザー詳細フォームやユーザー作成フォームでは、CustomUser
で追加した nickname
・height
・weight
の入力や変更も可能であり、管理画面から CustomUser
のユーザーの管理を行えていることを確認できると思います。
こんな感じで、admin.py
の変更により、独自で作成したユーザーの管理を行うことができるようになります。
ただ、上記の「ユーザー一覧リスト」にはユーザー名しか表示されていませんので一覧性が悪いですし、「ユーザー詳細フォーム」や「ユーザー作成フォーム」では CustomUser
の持つフィールド全てが表示されているので、ちょっと冗長な気もします。
さらに、ユーザー追加時等に入力したパスワードがそのまま表示されてセキュリティ的にもイマイチです。
こういった具合に、ユーザー管理を行う画面・フォーム等に不満がある場合は管理画面のカスタマイズを行なった方が良いです。
前述でも紹介しましたが、この管理画面(ユーザー管理画面)のカスタマイズ方法については下記ページで解説していますので、必要に応じて参考にしていただければと思います。
【Django】管理画面でカスタムユーザーを管理する(UserAdmin)フォーム・ビュー・テンプレートの作成
ここまでの変更によって、カスタムユーザーが定義され、カスタムユーザーを管理画面から管理・作成することができるようになりました。
最後に、カスタムユーザーをフォームやビュー等から利用する例を紹介していきます。
実現するページは3つのみで、1つ目はユーザーアカウント(カスタムユーザー)を追加するページ、2つ目はログインを行うページ、3つ目はログインユーザーのニックネームと BMI を表示するページになります。
ユーザーアカウントの作成やログインに関しては下記ページで詳しく解説していますので、これらを実現するための手段の詳細を知りたい方は下記ページを参照して頂ければと思います。
【Django】ログイン機能の実現方法(関数ベースビュー編)このページでは、スクリプトの紹介および、ユーザーに関連する説明のみを行なっていきたいと思います。
フォームの作成
まずは login_app
フォルダの下に forms.py
を新規作成し、中身を下記のように変更します。
from django import forms
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth import get_user_model
CustomUser = get_user_model()
class SignupForm(UserCreationForm):
class Meta:
model = CustomUser
fields = [CustomUser.USERNAME_FIELD] + CustomUser.REQUIRED_FIELDS + ['password1', 'password2']
class LoginForm(AuthenticationForm):
pass
UserCreationForm
や AuthenticationForm
に関しては先ほど紹介した 【Django】ログイン機能の実現方法(関数ベースビュー編) で解説していますので、詳細を知りたい方は【Django】ログイン機能の実現方法(関数ベースビュー編) をご参照ください。
上記でポイントになるのは、まず model
に models.py
に定義した CustomUser
を指定する点になります。この CustomUser
は、settings.py
で AUTH_USER_MODEL
に models.py
で定義した CustomUser
を指定している場合、上記のように get_user_model
から取得することが可能です。
また、SignupForm
の fields
には、CustomUser
作成時に必須となる情報が入力できるように、フォームで入力受付を行うフィールドをリスト形式で指定する必要があります。
USERNAME_FIELD
(username
)とパスワード(password1
・password2
)以外で入力受付を行いたいフィールドは CustomUser
の REQUIRED_FIELDS
で指定していますので、fields
にはこれらを連結したリストを指定すれば良いため、上記のように SignupForm
の fields
を指定するようにしています。
UserCreationForm
を継承したフォームの場合、fields
への指定に password1
・password2
を省略した場合でも、表示される入力フォームには password1
・password2
に対するエントリーが表示されます
テンプレートの作成
続いてテンプレートを作成していきます。
といっても、今回用意するテンプレートは基本的に下記ページの ログイン機能実現用のスクリプト で紹介している signup.html
・login.html
・user.html
とほぼ同等のものなので、詳細な説明は省略させていただきます(user.html
はニックネームと BMI を表示するように変更しています)。
これらのファイルの作成フォルダが login_app/templates/login_app/
であることに注意してください。
{% load static %}
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ユーザー登録</title>
</head>
<body>
<h1>ユーザー登録</h1>
<form action="{% url 'signup' %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<p><input type="submit" value="登録"></p>
</form>
</body>
</html>
{% load static %}
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ログイン</title>
</head>
<body>
<h1>ログイン</h1>
<p>{{message}}</p>
<form action="{% url 'login'%}" method="post">
{% csrf_token %}
{{ form.as_p }}
<p><input type="hidden" name="next" value="{{next}}"></p>
<p><input type="submit" value="ログイン"></p>
</form>
<p><a href="{% url 'signup'%}">ユーザー登録</a></p>
</body>
</html>
{% load static %}
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>{{title}}</title>
</head>
<body>
<h1>{{nickname}}</h1>
<p>BMI:{{bmi}}</p>
</body>
</html>
ビューの作成
次はビューを作成していきます。
こちらも基本的に下記ページの ログイン機能実現用のスクリプト で紹介している views.py
と似ている部分が多いのですが、簡略化して logout_view
や other_view
を削除したり、リダイレクト関連の処理を省略している部分もあるので注意してください。
また、user_view
では models.py
の CustomUser
でオーバーライドや定義を行なった get_short_name
や get_bmi
メソッドを使用し、このメソッドから取得した文字列や値をテンプレートに渡すようにしています。
from django.shortcuts import render, redirect
from .forms import SignupForm, LoginForm
from django.contrib.auth import login
from django.contrib.auth.decorators import login_required
def signup_view(request):
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
return redirect(to='/login_app/user/')
else:
form = SignupForm()
param = {
'form': form
}
return render(request, 'login_app/signup.html', param)
def login_view(request):
if request.method == 'POST':
next = request.POST.get('next')
form = LoginForm(request, data=request.POST)
if form.is_valid():
user = form.get_user()
if user:
login(request, user)
return redirect(to='/login_app/user/')
else:
form = LoginForm()
param = {
'form': form,
}
return render(request, 'login_app/login.html', param)
@login_required
def user_view(request):
user = request.user
params = {
'nickname': user.get_short_name(),
'bmi': user.get_bmi()
}
return render(request, 'login_app/user.html', params)
1つ説明を加えておくと、user_view
関数の引数 request
のデータ属性 user
は settings.py
の AUTH_USER_MODEL
に指定したモデルのインスタンスとなります。
AUTH_USER_MODEL
には models.py
で定義した CustomUser
を指定しているため、request.user
は CustomUser
のインスタンス(より具体的にはページにアクセスしてきたユーザーのインスタンス)となりますので、request.user
に CustomUser
で定義したメソッドを実行させることができます。
実際に、上記の user_view
関数では get_short_name
と user.get_bmi
メソッドを実行させています。もちろんメソッドだけでなく、CustomUser
に用意されているクラス変数やデータ属性(インスタンス変数)も利用可能です。
スポンサーリンク
パスとビューの関連付け
最後にパスとビューの関連付けを行なっていきます。
まず login_project
フォルダの下の urls.py
を下記のように変更し、login_app/
から始まるパスが指定された際に login_app
フォルダ下の urls.py
を参照するようにします。
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('login_app/', include('login_app.urls'))
]
続いて、その参照先となる urls.py
を login_app
フォルダの下に下記のように作成します。
これにより、path
の第1引数で指定したパス(URL)へのアクセスがあった際に、第2引数で指定した views.py
の各関数が実行されるようになります。
from . import views
from django.urls import path
urlpatterns = [
path('signup/', views.signup_view, name='signup'),
path('login/', views.login_view, name='login'),
path('user/', views.user_view, name='user'),
]
動作確認
ここまでフォームやビューの作成を行なってきましたので動作確認をしてみましょう!
まずは Django 開発用ウェブサーバーを起動し(python manage.py runserver
を実行)、さらに下記 URL をウェブブラウザで開いてみてください。
http://localhost:8000/login_app/signup/
そうすると、下の図のようなユーザー登録フォームが表示されるはずです。
forms.py
で SignupForm
の fields
に指定したフィールドへの入力を行うことができるようになっている点を確認できると思います。
さらに、上の図の登録フォームにユーザー名やニックネーム等の全ての入力を行なった後に 登録
ボタンを押せば、次は下の図のようなユーザーの情報表示ページに遷移するはずです。
このページでは、ユーザーのニックネームと BMI が表示されるようになっています。これらの文字列や値は、ビューで CustomUser
のメソッドを実行することで取得され、それらをテンプレートに組み込むことでページとして表示された結果となります。
最後に下記 URL をウェブブラウザで表示してみてください。
http://localhost:8000/login_app/login/
今度は下の図のようなログインフォームが表示されるはずです。
このログインフォームに、今度は スーパーユーザーの追加 で追加したユーザーのユーザー名とパスワードを入力して ログイン
ボタンを押してみてください。ログインに成功し、先ほど同様にユーザー情報表示ページに遷移するはずです。
ただし、表示されるニックネームや BMI は スーパーユーザーの追加 で追加したユーザーのものに変化しているはずです。
これは、views.py
の user_view
で、ログインしたユーザーのニックネームや BMI を表示するようにしているためです。より具体的には、request.user
に get_short_name
や get_bmi
のメソッドを実行させているからです。
こういった動作から、models.py
で作成した CustomUser
を利用してログインが実現されていることや、CustomUser
に定義したメソッドを利用してログインユーザーに応じた情報表示が実現できていることを確認できると思います。
今回示した例は簡単なものになりますが、カスタムユーザーを作り込み、それに合わせてビューやフォームを作成することで、様々なアプリを実現することができることを理解していただけたのではないかと思います!
まとめ
このページでは、Django での「カスタムユーザー」の作り方について解説しました!
カスタムユーザーは AbstractUser
を継承することで簡単に作成することが出来ます。
ただし、カスタムユーザーを作成した場合は settings.py
での AUTH_USER_MODEL
の設定が必要であることに注意してください。
また、アプリ運用開始後に User
からカスタムユーザーにモデル自体を変更してしまうとマイグレーションが大変(エラーを解消するのが大変)なので、アプリ開発時はできるだけ早い段階でカスタムユーザーの作成を行なった方が良いと思います。
長々と解説をしましたが、ポイントは開発したいアプリに合わせてカスタムユーザーのフィールドやメソッドを追加すること、さらに、追加したフィールドやメソッドに合わせて管理画面やフォーム・ビューを作成する必要がある点になると思います。
このポイントさえしっかり理解しておけば、カスタムユーザーの作成および利用はそんなに難しくないと思います。
カスタムユーザーを導入すれば、開発できるアプリの幅も広がりますので、是非カスタムユーザーの作り方は覚えておいてください!
また、ページの中でも少し触れたように、AbstractUser
ではなく AbstractBaseUser
を継承することで、より柔軟にカスタムユーザーを作成することができるようになります。AbstractBaseUser
を継承してカスタムユーザーを作成する手順は下記ページで解説していますので、必要に応じてこちらも是非参考にしてください!
[…] だえうホームページ 【Django】カスタムユーザー(独自のユーザー)の作り方【AbstractUser編】 このページでは、Django での「カスタムユーザー」の作り方について解説していきます。 […]