Question

As my title says, I want to know if I there's a way to allow a user to use not only his username, but also his user's email to login. I want to standardize the login procedure because at the moment I'm having my users use many different conventions and it gets pretty messy.

Was it helpful?

Solution

You could probably do this if you enforce unique email addresses. Meaning no user can have the same e-mail address. This way you could fetch the user by e-mail address and log them in.

The form might look something like this:

<form method="post" action="{% url myproject.views.login %}">
     <p>Username</p>
     <input type='text' name='username'/>

     <p>Password</p>
     <input type='password' name='password'/>
     <input type="submit" value="Login"/>
</form>

The view method might look something like this:

def login( request ):
    username = request.POST['username']
    password = request.POST['password']
    user = User.objects.filter( email = username )[0]
    if( user is not None ):
         # -- the user was retrieved by an email address
         # -- now you can authenticate and log them in log them in
         from django.contrib import auth
         user = auth.authenticate( user.username, password )
         if( user is not None ):
              auth.login( user, request )

OpenID might be another way to go: http://bit.ly/a2OlHX

Ensure unique e-mail addresses per user: http://bit.ly/aOaAbw

OTHER TIPS

I think I 'solved' my problem, at least it's functional, for now. I decided to use my own authentication backend. I created a file 'auth_backends.py' and added it to AUTHENTICATION_BACKENDS in my settings.py:

My login form fields only contain 'username' and password. The only way I'm doing to check if the entered username is in fact his username or email, is by doing the .find('@'). Is there a better way to check for it? Would this be enough? The whole reason I'm doing this is because it's easier for the user to remember his/her email than his username (which is actually an 'id' consisting of numbers).

I'm also going to have to take care of duplicate emails.

from django.conf import settings
from django.contrib.auth.backends import ModelBackend
from django.core.exceptions import ImproperlyConfigured
from django.db.models import get_model
from django.contrib.auth.models import User

class CustomUserModelBackend(ModelBackend):

def authenticate(self, **credentials):
    if 'username' in credentials:
        if credentials['username'].find('@') > 0:
            return self.authenticate_by_email(**credentials)
        else:
            return self.authenticate_by_username(**credentials)

def authenticate_by_username(self, username=None, password=None):
    try:
        user = User.objects.get(username=username)
        if user.check_password(password):
            return user
    except User.DoesNotExist:
        return None

def authenticate_by_email(self, username=None, password=None):
    try:
        user = User.objects.get(email=username)
        if user.check_password(password):
            return user
    except User.DoesNotExist:
        return None
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top