ここまでの作業の結果では,新規にユーザ登録をしてまだメールによるアカウント有効化を終えていないユーザがログインしようとしたときに,「ID とパスワードが異なります」というメッセージが表示されてしまいます.ここでは未検証ユーザのログインエラーメッセージを変更してみよう.
まず,ユーザ user_e の is_active を 0 に変更します.
sqlite> select id, username, is_active, email from users_user; ⏎ id|username|is_active|email 1|user_a|1|a@sample.com 2|user_b|1|b@sample.com 3|user_c|1|c@sample.com 4|root|1|root@example.com 7|user_e|1|e@sample.com sqlite> update users_user set is_active = 0 where id = 7; ⏎ sqlite> select id, username, is_active, email from users_user; ⏎ id|username|is_active|email 1|user_a|1|a@sample.com 2|user_b|1|b@sample.com 3|user_c|1|c@sample.com 4|root|1|root@example.com 7|user_e|0|e@sample.com sqlite>
アカウントが有効化された user_a のエラーメッセージです.
アカウントの検証を終えていないユーザ user_e でも同じエラーメッセージが表示され,これは不親切かもしれません.
エラーメッセージの処理は forms.py に記述します.
users/forms.py
class AuthenticationForm(forms.Form):
    """
    Base class for authenticating users. Extend this to get a form that accepts
    username/password logins.
    """
    username = UsernameField(widget=forms.TextInput(attrs={"autofocus": True}))
    password = forms.CharField(
        label=_("Password"),
        strip=False,
        widget=forms.PasswordInput(attrs={"autocomplete": "current-password", 'class': 'form-control'}),
    )
    error_messages = {
        "invalid_login": _(
            "Please enter a correct %(username)s and password. Note that both "
            "fields may be case-sensitive."
        ),
        "inactive": _("This account is inactive."),
    }
    def __init__(self, request=None, *args, **kwargs):
        """
        The 'request' parameter is set for custom auth use by subclasses.
        The form data comes in via the standard 'data' kwarg.
        """
        self.request = request
        self.user_cache = None
        super().__init__(*args, **kwargs)
        # Set the max length and label for the "username" field.
        self.username_field = UserModel._meta.get_field(UserModel.USERNAME_FIELD)
        username_max_length = self.username_field.max_length or 254
        self.fields["username"].max_length = username_max_length
        self.fields["username"].widget.attrs["maxlength"] = username_max_length
        if self.fields["username"].label is None:
            self.fields["username"].label = capfirst(self.username_field.verbose_name)
    def clean(self):
        username = self.cleaned_data.get("username")
        password = self.cleaned_data.get("password")
        if username is not None and password:
            # is_active が 0 のときに authenticate が None になってしまうため
            inactive_user = UserModel.objects.filter(username=username)
            if len(inactive_user) > 0:
                if not inactive_user[0].is_active:
                    self.add_error('username', 'ログインする前にメールの検証を行ってアカウントを有効化してください.')
                    self.add_error('username', 'ユーザ登録後にメールが届いているはずです.アカウントを有効化するにはそのメールの指示に従ってください.')
                    self.add_error('username', '検証メールの有効期限が切れた場合はユーザ登録ページからメールを再送信してください.')
                    raise ValidationError(
                        self.error_messages["inactive"],
                        code="inactive",
                    )
            self.user_cache = authenticate(
                self.request, username=username, password=password
            )
            if self.user_cache is None:
                raise self.get_invalid_login_error()
            else:
                self.confirm_login_allowed(self.user_cache)
        return self.cleaned_data
アカウントの検証を終えていないユーザ user_e のエラーメッセージが変更されました.