我的表单只允许用户通过用户名登录。我决定只允许用户通过电子邮件而不是用户名登录。
首先,这不是与通过电子邮件进行日志记录相关的任何问题的重复,因为在我的方案中,我在forms.py
中验证并验证用户,然后再进入最终登录视图,这样就给了我机会为错误的登录密码等引发错误。
我面临的问题是我修改了我的forms.py
以引发错误,如果电子邮件不存在有效,但它不会让用户通过他的电子邮件登录。
def LoginRequest(request):
form = LoginForm(request.POST or None)
if request.POST and form.is_valid():
user = form.login(request)
if user:
login(request, user)
return HttpResponseRedirect(reverse('Hello'))
return render(request, 'login.html',{'form': form})
这是我的原始代码,只允许用户通过用户名
登录 class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(
widget=forms.PasswordInput(render_value=False)
)
def clean(self):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if not user or not user.is_active:
raise forms.ValidationError("Sorry, that login was invalid. Please try again.")
return self.cleaned_data
def login(self, request):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
user = authenticate(username=username, password=password)
return user
这是我修改过的代码,只允许用户通过电子邮件登录。我想了很多我会怎么做但这是我提出的最好的主意。对不起,这有点令人困惑。 问题是,它不会让用户登录。我不明白为什么。
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(
widget=forms.PasswordInput(render_value=False)
)
def clean(self):
user = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if User.objects.filter(email=user).exists():
password = self.cleaned_data.get('password')
user = authenticate(username=user.username, password=password)
if not user or not user.is_active:
raise forms.ValidationError("Sorry, that login was invalid. Please try again.")
return self.cleaned_data
def login(self, request):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
user = authenticate(username=username, password=password)
return user
有人可以帮帮我吗?
答案 0 :(得分:7)
由于dougis
指出您正在尝试使用电子邮件对用户进行身份验证,但authenticate
函数会根据用户名和密码对用户进行身份验证。所以这是使用电子邮件验证用户的技巧(完整的工作表单):
from django.db.models import Q
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth.models import User
from django import forms
from django.contrib.auth import authenticate
class LoginForm(forms.Form):
email = forms.CharField()
password = forms.CharField(
widget=forms.PasswordInput(render_value=False)
)
def clean(self):
user = self.authenticate_via_email()
if not user:
raise forms.ValidationError("Sorry, that login was invalid. Please try again.")
else:
self.user = user
return self.cleaned_data
def authenticate_user(self):
return authenticate(
username=self.user.username,
password=self.cleaned_data['password'])
def authenticate_via_email(self):
"""
Authenticate user using email.
Returns user object if authenticated else None
"""
email = self.cleaned_data['email']
if email:
try:
user = User.objects.get(email__iexact=email)
if user.check_password(self.cleaned_data['password']):
return user
except ObjectDoesNotExist:
pass
return None
views.py
def LoginRequest(request):
form = LoginForm(request.POST or None)
if request.method == 'POST' and form.is_valid():
user = form.authenticate_user()
login(request, user)
return HttpResponseRedirect(reverse('Hello'))
return render(request, 'login.html',{'form': form})
答案 1 :(得分:5)
您还可以编写自定义后端:
# yourapp.backends.py
from django.contrib.auth.models import User
class EmailOrUsernameModelBackend(object):
""" Authenticate user by username or email """
def authenticate(self, username=None, password=None):
if '@' in username:
kwargs = {'email': username}
else:
kwargs = {'username': username}
try:
user = User.objects.get(**kwargs)
if user.check_password(password):
return user
else:
return None
except User.DoesNotExist:
return None
def get_user(self, user_id=None):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
现在将后端添加到settings.py:
AUTHENTICATION_BACKENDS = (
'yourapp.backends.EmailOrUsernameModelBackend',
'django.contrib.auth.backends.ModelBackend',
)
答案 2 :(得分:1)
看起来您正在测试2个不同的字段。 您根据电子邮件查找用户
if User.objects.filter(email=user).exists():
但随后验证用户名
user = authenticate(username=user, password=password)
如果您使用的是电子邮件地址,则认证行应为
user = authenticate(email=user, password=password)