首页 > 解决方案 > 使用自定义 AuthenticationForm 覆盖 Django LoginView 错误消息

问题描述

我有一个基于类的子类视图LoginView

from django.contrib.auth.views import LoginView

class CustomLoginView(LoginView):

def get_success_url(self):
    url = self.get_redirect_url()
    return url or reverse_lazy('knowledgebase:user_home', kwargs={
        'username':self.request.user.username,
    })

如果用户的电子邮件尚未激活,我想覆盖错误消息,因为他们必须单击发送到其电子邮件地址的链接。当前的默认消息如下所示:

覆盖 LoginView 错误消息

而不是说:

请输入正确的电子邮件地址和密码。两个地方都要注意大小写。

我想说几句大意:

请确认您的电子邮件,以便您可以登录。

我试过了:

帐户/forms.py

from django.contrib.auth.forms import AuthenticationForm
from django.utils.translation import gettext as _

class PickyAuthenticationForm(AuthenticationForm):
    def confirm_login_allowed(self, user):
        if not user.is_active:
            raise forms.ValidationError(
                _("Please confirm your email so you can log in."),
                code='inactive',
            )

帐户/views.py

class CustomLoginView(LoginView): # 1. <--- note: this is a class-based view

    form_class = PickyAuthenticationForm # 2. <--- note: define form here?

    def get_success_url(self):
        url = self.get_redirect_url()
        return url or reverse_lazy('knowledgebase:user_home', kwargs={
            'username':self.request.user.username,
        })

当我尝试使用确实存在但尚未验证其电子邮件地址的用户登录时,结果绝对无效。

AuthenticationForm 文档

标签: djangoformsdjango-authenticationloginview

解决方案


方法 - 1

Django 使用ModelBackend默认值AUTHENTICATION_BACKENDS,它不对非活动用户进行身份验证。

这也在对非活动用户的授权部分中进行了说明,

非活动用户是其is_active字段设置为的用户False。和 ModelBackend身份RemoteUserBackend验证后端禁止这些用户进行身份验证。如果自定义用户模型没有is_active字段,则将允许所有用户进行身份验证。

所以,设置AllowAllUsersModelBackend为你AUTHENTICATION_BACKENDSsettings.py

# settings.py

AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.AllowAllUsersModelBackend']

它对我的 Django 应用程序有多大影响?

它不会影响身份验证以外的任何内容。如果我们查看类的源代码,AllowAllUsersModelBackend我们可以看到它只是允许非活动用户进行身份验证。


方法 - 2

就个人而言,我不推荐这种方法,因为方法 1是 Django 解决这个问题的方法。

覆盖类的clean(...)方法PickyAuthenticationForm并将AllowAllUsersModelBackend后端称为,

from django.contrib.auth.backends import AllowAllUsersModelBackend


class PickyAuthenticationForm(AuthenticationForm):
    def clean(self):
        username = self.cleaned_data.get('username')
        password = self.cleaned_data.get('password')

        if username is not None and password:
            backend = AllowAllUsersModelBackend()
            self.user_cache = backend.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

    def confirm_login_allowed(self, user):
        if not user.is_active:
            raise forms.ValidationError(
                "Please confirm your email so you can log in.",
                code='inactive',
            )

结果截图

截屏


推荐阅读