I have a form that only allow users to login via username . I decided to only allow user to login via email instead of username.
First, this is not a duplication of any
Looks like you are testing against 2 different fields. You look for the user against email
if User.objects.filter(email=user).exists():
but then validate against username
user = authenticate(username=user, password=password)
If you are using the email address the auth line should be
user = authenticate(email=user, password=password)
You can also write a custom backend:
# 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
Now add your backend to settings.py:
AUTHENTICATION_BACKENDS = (
'yourapp.backends.EmailOrUsernameModelBackend',
'django.contrib.auth.backends.ModelBackend',
)
As dougis
pointed out you are trying to authenticate the user using email, But authenticate
function authenticates user based on username and password. So here is the trick to authenticate the user using email (complete working form):
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})