我有一个基于类的视图,该视图将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,
})
如果用户的电子邮件尚未激活,我想覆盖该错误消息,因为他们必须单击发送到其电子邮件地址的链接。当前的默认消息如下:
与其说:
请输入正确的电子邮件地址和密码。注意两者 字段可能区分大小写。
我想说些什么:
请确认您的电子邮件,以便您登录。</ p>
我尝试过:
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',
)
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,
})
当我尝试使用确实存在但尚未验证其电子邮件地址的用户登录时,结果绝对无效。
答案 0 :(得分:2)
您需要使用AllowAllUsersModelBackend
在这里,您将获得有关设置自定义后端的说明
https://docs.djangoproject.com/en/3.0/topics/auth/customizing/#specifying-authentication-backends
希望有帮助。
答案 1 :(得分:2)
Django使用ModelBackend
作为默认AUTHENTICATION_BACKENDS
,并且不对不活动的用户进行身份验证。
Authorization for inactive users部分中也对此进行了说明,
非活动用户是指其
is_active
字段设置为False
的用户。的ModelBackend
和RemoteUserBackend
身份验证后端禁止 这些用户无法进行身份验证。如果自定义用户模型没有is_active
字段,将允许所有用户进行身份验证。
因此,在 AUTHENTICATION_BACKENDS
AllowAllUsersModelBackend
设置为您的 settings.py
# settings.py
AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.AllowAllUsersModelBackend']
除了身份验证外,它不影响其他任何内容。如果我们查看source code of AllowAllUsersModelBackend
class,就可以看到它只允许 非活动 用户进行身份验证。
我个人不建议使用此方法,因为 method-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',
)
结果屏幕截图
答案 2 :(得分:0)
当我只是想覆盖一条消息时,我不认为设置自定义后端是解决方案。我通过定义form_invalid
进行了临时修复。是的,它很hacky,但现在就可以解决问题。怀疑这将帮助任何人,但发现form.errors
很有趣。也许有人可以以此为基础解决他们的特定问题。
def form_invalid(self, form):
"""If the form is invalid, render the invalid form."""
#TODO: This is EXTREMELY HACKY!
if form.errors:
email = form.cleaned_data.get('username')
if User.objects.filter(email=email, username=None).exists():
if len(form.errors['__all__']) == 1:
form.errors['__all__'][0] = 'Please confirm your email to log in.'
return self.render_to_response(self.get_context_data(form=form))