Djangoで独自ユーザーモデルを実装する。

# はじめに
Djangoではデフォルトでユーザーモデルを持っているため、独自で作成する必要なないような気がしますが、[ここ](http://https://qiita.com/NAKKA-K/items/7627b6a22f364941b989)などで紹介されている通り、ユーザーモデルは最初からカスタマイズして使用する方が良いようです。
一番シンプルだと思われる独自ユーザーモデルの作成の方法を紹介します。

# 検証環境
OS：Windows7 Professional
Pythonがすでにインストールされていて、パスが登録されていること。
Macの場合はコマンドなどを少々読み替えてください。ソースコードは同じで問題ありません。

```
$ python --version
Python 3.6.6
```

以下のライブラリがインストールされているものとします。

```
$ pip freeze
Django==2.1.1
pytz==2018.5
```

# プロジェクトとアプリケーションの作成
以下のコマンドでプロジェクトとアプリケーションを作成します。

```
プロジェクトを作成
$ django-admin.py startproject project

プロジェクトフォルダに移動
$ cd project

アプリケーション作成
$ manage.py startapp user
```

### プロジェクトにアプリケーションを登録
settings.pyに作成したアプリケーションを登録します。

```python:project/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'user',                           # 追加
]
```

# ユーザーモデルの作成
AbstractBaseUserとPermissionMixinを多重継承したクラスを作成します。多重継承は少々気持ち悪いですが、割り切ります。
AbstractBaseUserはユーザー名やメールアドレスなどのユーザー情報を管理するクラス。
PermissionMixinはスーパーユーザー権限、グループ、パーミッションなどの権限周りを管理するクラス。
権限周りはPermissionMixinに任せてしまって大丈夫ですが、AbstractBaseUserに少々癖があります。

```python:user/models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, UserManager
from django.contrib.auth.validators import UnicodeUsernameValidator
from django.utils.translation import gettext_lazy as _

class User(AbstractBaseUser, PermissionsMixin):
    user_vali = UnicodeUsernameValidator()
    username = models.CharField(_('username'), max_length=150, unique=True, validators=[user_vali])
    email = models.EmailField(_('email address'), unique=True)
    is_staff = models.BooleanField(_('staff status'), default=False)

    objects = UserManager()

    EMAIL_FIELD = 'email'
    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['email']
```

ユーザー情報にはusername、email、is_staffの3つのフィールドが最低でも必要なようです。
UnicodeUsernameValidatorは正規表現（^[\w.@+-]+$）の一致でチェックをする模様。
createsuperuserを行う場合は、USERNAME_FIELDとREQUIRED_FIELDSに設定されている項目の入力が必要になる。
また管理画面ではUSERNAME_FIELDに設定されいる項目と、パスワードでログインすることになる。
emailでログインするには[こちら](https://qiita.com/cortyuming/items/2167a29a90c94bb4b1bb)を参照。
gettext_lazyは、特定の文字列をローカライズしてくれる。

### ユーザーモデルを設定

上記で作成したユーザーモデルをDjangoのユーザーモデルとして設定します。

```python:project/settings.py
AUTH_USER_MODEL = 'user.User'           # 追加
```

user.models.Userにモデルを配置しますが、user.Userでいいみたいです。

### 管理画面作成
きれいな管理画面も作成できますが、最低限で。

```python:user/admin.py
from django.contrib import admin
from .models import User

admin.site.register(User)
```

# データベースの作成
ユーザーモデルの登録が終わったので、データベースの作成を行います。

```
マイグレーションファイル作成
$ manage.py makemigrations
Migrations for 'user':
  user\migrations\0001_initial.py
    - Create model User

マイグレートする
$ manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, user
Running migrations:
  Applying contenttypes.0001_initial... OK
　　　　（割愛）
```

### スーパーユーザー作成
以下のコマンドでユーザー情報を作成します。

```
$ manage.py createsuperuser
Username: admin
Email: admin@example.com
Password:
Password (again):
Superuser created successfully.
```

ユーザーモデルのUSERNAME_FIELDにusername、REQUIRED_FIELDSにemailを設定しているので、その2項目とパスワードの入力が求められます。

# WEBサーバーの起動
WEBサーバーを起動して管理画面からユーザーモデルを確認します。
以下のコマンドでWEBサーバーを起動してください。

```
$ manage.py runserver
```

サーバーが起動したらブラウザから「[http://127.0.0.1:8000/admin/](http://127.0.0.1:8000/admin/)」にアクセスして管理画面を開きます。

|<img src="https://qiita-image-store.s3.amazonaws.com/0/269311/d15011f7-4637-abee-ebbc-33068c1fc35c.png">|<img src="https://qiita-image-store.s3.amazonaws.com/0/269311/b9dcbd68-254f-baed-b0e7-56a3b11e62e4.png">|<img src="https://qiita-image-store.s3.amazonaws.com/0/269311/63f99e6a-4bce-b698-d1a0-bf22d1a1ae16.png">|
|---|---|---|

ここまではデフォルトのユーザーモデルとあまり変わりません。画像は日本語にローカライズした状態です。
ユーザーモデルの編集画面は以下のように表示されます。

![スクリーンショット 2018-10-07 20.52.09.png](https://qiita-image-store.s3.amazonaws.com/0/269311/c82410e5-1ec4-0596-dd0d-069eba58f4f3.png)

作成したユーザーモデルの3つのフィールドが一番下に表示されています。それ以外の項目は権限周りの項目なのでPermissionMixinから引き継いだ項目だと思います。（未確認です）
また、作成したユーザーモデルの項目名は「username」「email address」「staff status」の3つですが、それぞれ「ユーザー名」「メールアドレス」「スタッフ権限」と表示されています。これはgettext_lazyがローカライズしてくれています。

デフォルトのUserクラスよりフィールドが少ないですが、必要なフィールドはユーザーモデルに追加していけばここにも反映されます。
既存のフィールドで必要な物がある場合は、AbstractUserクラスのソースコードを参考にするといいかもしれません。（環境によりますが、Windowsでは通常この辺にあると思います。C:\Program Files\Python36\Lib\site-packages\djaogn\contrib\auth\models.py）