ユーザー名の代わりにメールアドレスを使用するようUserモデルをカスタマイズした場合のdjango-allauthの利用について

(2019/1/25 ACCOUNT_USER_MODEL_USERNAME_FIELDについて追記)

# 環境

- Python 3.6.6
- Django 2.1.5  
- django-allauth 0.38.0 

# エラー内容

DjangoのUserモデルについて、

- ユーザー名とパスワード

ではなく

- メールアドレスとパスワード

で認証するようにカスタマイズした上で、django-allauthを使用したところ、

- ログインページ(`accounts/login/`)
- サインアップページ(`accounts/signup/`)

にアクセスしたら、以下のエラーになりました。

`username`フィールドが無い、とのこと。

```
  File "/Users/（略）/venv/lib/python3.6/site-packages/allauth/utils.py", line 68, in get_username_max_length
    max_length = User._meta.get_field(USER_MODEL_USERNAME_FIELD).max_length
  File "/Users/（略）/venv/lib/python3.6/site-packages/django/db/models/options.py", line 566, in get_field
    raise FieldDoesNotExist("%s has no field named '%s'" % (self.object_name, field_name))
django.core.exceptions.FieldDoesNotExist: User has no field named 'username'

```
# 対処方法

settings.pyに以下を追加します。

```python:settings.py
ACCOUNT_AUTHENTICATION_METHOD = 'email' # 認証方法をメールアドレスにする
ACCOUNT_USER_MODEL_USERNAME_FIELD = None # Userモデルにusernameは無い
ACCOUNT_EMAIL_REQUIRED = True # メールアドレスを要求する
ACCOUNT_USERNAME_REQUIRED = False　# ユーザー名を要求しない
```

ログインページ(`accounts/login/`)にアクセスすると無事に以下の画面が表示されるようになりました。

![スクリーンショット 2019-01-20 19.00.49-min.png](https://qiita-image-store.s3.amazonaws.com/0/317369/78664619-1f0f-7be4-9e4c-004a795188a3.png)


なお、`ACCOUNT_USER_MODEL_USERNAME_FIELD = None`を設定しなくても、

- ログインページ(`accounts/login/`)へのアクセス
- ログイン
- サインアップページ(`accounts/signup/`)へのアクセス

までは可能なのですが、実際にサインアップを行おうとすると`NotImplementedError at /accounts/signup/`のエラーになってしまいます。

ですので、`ACCOUNT_USER_MODEL_USERNAME_FIELD`についても設定してください。

# 補足情報：Userモデルのカスタマイズ内容

なお、補足情報としてUserモデルのカスタマイズ内容は以下の通りです。

```python:users/models.py:
from django.db import models
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.models import AbstractBaseUser
from django.utils.translation import gettext_lazy as _
from django.utils import timezone


class User(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.'),
    )
    is_active = models.BooleanField(
        _('active'),
        default=True,
        help_text=_(
            'Designates whether this user should be treated as active. '
            'Unselect this instead of deleting accounts.'
        ),
    )
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

    objects = UserManager()

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

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')

    @property
    def username(self):

        return self.email
```

# 参考

- [【英語】django-allauth公式ドキュメント Configuration ](https://django-allauth.readthedocs.io/en/latest/configuration.html)

- [爆速で作れるDjangoユーザ認証機能【django-allauth】]( https://sinyblog.com/django/django-allauth/)

- [現場で使える Django の教科書《実践編》] (https://www.amazon.co.jp/%E7%8F%BE%E5%A0%B4%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B-Django-%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8%E3%80%8A%E5%AE%9F%E8%B7%B5%E7%B7%A8%E3%80%8B-%E6%A8%AA%E7%80%AC-%E6%98%8E%E4%BB%81-ebook/dp/B07L3DRGBT)

- [Django ユーザー カスタマイズ方法](https://qiita.com/okoppe8/items/10ae61808dc3056f9c8e)

- [naritoブログ Userモデルのカスタマイズ](https://narito.ninja/detail/39/)