【Django】ユーザー名でもメールアドレスでもログインできるようにする【認証】

Djangoの認証機能はデフォルトでユーザー名とパスワードでのログインができます。
しかし、最近はユーザー名かメールアドレス、どちらでも使える場合が多いです。

カスタマイズ方法には

  • フォームをカスタマイズする
  • バックエンド認証機能をカスタマイズする

の2パターンがあります。
認証機能を拡張して、ログインを使いやすくしていきましょう。

ユーザー名でもメールアドレスでもログインできるようにする

準備:ユーザーモデルをカスタマイズする

Djangoはデフォルトで用意されているUserモデルを使用することを非推奨としています。
それゆえに今回は新しくCustomUserというクラスを作成することにします。

今回はログインが主ですので詳細な説明はしません。
また既にユーザーモデルをカスタマイズしている方は読み飛ばしてください。

models.py

CustomUserクラスを用いてログイン機能をカスタマイズします。

①フォームをカスタマイズする方法

この方法ではforms.pyとviews.pyをカスタマイズします。

forms.py
cleanメソッドをカスタマイズ

このクラスはログインフォームを表示するためのクラスとなっていて、cleanメソッドを拡張しています。
cleanメソッドはフォームの値のバリデーションを行うメソッドとなっていて、その一番下で認証を行っています。

authenticate関数が認証を行う関数です。
ログイン処理というのは3段階に分かれ、値のバリデーション→認証→ログインという形になります。

このフォームクラスでは、値のバリデーションと認証を行っていることになります。

パスワードかメールアドレスかを判別

「@」が入っていればメールアドレス。そうでなければユーザー名として処理を分岐しています。
今回は簡易な方法でメールアドレスかどうかを判断したために、ユーザー登録の段階でユーザー名に「@」を使えなくする必要があります。

もっと厳密にメールアドレスだと判断したい場合は、正規表現などを使用すると良いでしょう。

views.py

Viewではログインの3段階の内、最後であるログイン処理を行っています。

②バックエンド認証機能をカスタマイズする方法

続いてはDjangoのバックエンド側にある認証システムをそもそもカスタマイズしてしまう方法です。
こちらの手法の方が多く見受けられる気がします。

まず、アプリのフォルダ内にauth_backends.pyというファイルを作成します。

auth_backends.py

ModelBackendクラスを拡張しています。
内容に関しては①で行ったようなユーザー名かメールアドレスかの判断、バリデーションです。

ログインをさらに強固にするならば、もっとバリデーションの種類を増やしても良いでしょう。
このファイルを認識させるために、プロジェクトのsettings.pyに追記します。

settings.py

こちらの方法でもforms.pyに追記が必要ですが、その記述量は①と比べてかなり削減されています。

forms.py

認証に関しては先ほど作成したauth_backends.pyが担ってくれているので、フォームの表示を変えているだけです。
同様にViewに関しても記述量が減っています。

views.py

先ほど設定したformクラスとテンプレートを指定するだけのシンプルな実装となっています。

おわりに

2つの方法を紹介しましたが、認証バックエンド機能に関してはさまざまな場所で認証する場合に便利な手法です。
一方で、小規模のシステムでログインくらいにしか認証を使用しない場合にはフォームのカスタマイズで事足りるでしょう。