Use email addresses for user name

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from django.contrib.auth.models import User
from django.core.validators import email_re

class BasicBackend:
    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

class EmailBackend(BasicBackend):
    def authenticate(self, username=None, password=None):
        #If username is an email address, then try to pull it up
        if email_re.search(username):
            try:
                user = User.objects.get(email=username)
            except User.DoesNotExist:
                return None
        else:
            #We have a non-email address username we should try username
            try:
                user = User.objects.get(username=username)
            except User.DoesNotExist:
                return None
        if user.check_password(password):
            return user

More like this

  1. Authenticate with Email Address by thom 7 years ago
  2. Email or username authentication with masquerading by petrilli 4 years, 10 months ago
  3. Google Account authentication by Hangya 3 years, 7 months ago
  4. Login with email or username by zeeg 5 years, 7 months ago
  5. SeparatedValuesField by jezdez 6 years, 4 months ago

Comments

bluszcz (on March 15, 2007):

Does it works admin app? In my case not :)

#

robbie (on April 16, 2007):

This is certainly a useful snippet, but it seems a little over complicated. What's wrong with just:

from django.contrib.auth.backends import ModelBackend
from django.core.validators import email_re
from django.contrib.auth.models import User

class EmailBackend(ModelBackend):
    def authenticate(self, username=None, password=None):
        if email_re.search(username):
            try:
                user = User.objects.get(email=username)
                if user.check_password(password):
                    return user
            except User.DoesNotExist:
                return None
        return None

...and then just adding it in front of Django's ModelBackend?

AUTHENTICATION_BACKENDS = (
    "emailauth.EmailBackend",
    "django.contrib.auth.backends.ModelBackend",
)

#

adurdin (on May 4, 2007):

The admin login view displays a message "Your email address is not your username" if you attempt to login with an email address and password that do not match (e.g. mistyped the password).

#

Paperface (on May 14, 2007):

adurdin: Alter your template registration/login.html to reflect the change in authentication method.

chris: Just thought I'd let you know, I'm using this and it seems to work very well

Thanks

#

zgoda (on July 12, 2007):

The problem is, the email field in User model is not unique, so you have to do 2 things: monkeypatch your database by addinng necessary constraint to the email field and generate some-kind-of-unique username. Unfortunately, the field is only allowed to keep 30 characters, so you cann't just use munged email or md5 hash for username...

#

zgoda (on August 28, 2007):

More problems with this. Users of our applications keep reporting me various places in django's own admin where "weird" usernames are shown. Sometimes it's really hard to customize admin templates to display something other than default __str__ provided by Django. I'm thinking on dynamic replacing __str__ in django.contrib.auth.models.User, maybe using signals?

#

mawoodall (on November 9, 2007):

The key to having this work with user object functions like 'has_perm()' and the admin interface is that you have to add both the new and default backends to your settings file:

'AUTHENTICATION_BACKENDS = ( 'yourproject.email-auth.EmailBackend', "django.contrib.auth.backends.ModelBackend", ) '

#

cogat (on January 17, 2008):

One other thing - the max_length for username in contrib.auth.forms.login is 30. It should be increased to the length of the email field, 75 characters by default.

#

Rich (on February 7, 2008):

One other thing - the max_length for username in contrib.auth.forms.login is 30. It should be increased to the length of the email field, 75 characters by default

Sorry if this is a dumb question, but what would be the correct way to do that?

#

lars.yencken (on May 9, 2008):

Rich: Probably two ways. Firstly, you can manually alter the database yourself after running syncdb. In fact, you could hook a callback onto the post_syncdb signal to do it automatically every time. Secondly, you could simply edit the django source which is installed to change the field width. Find and edit the User class in django/contrib/auth/models.py.

#

crucialfelix (on June 28, 2008):

lars: I misread this the first time too. cogat is saying the the FORM field is limited to 30 chars. nothing to do with the db. the database still stores a username (whatever you want, random, truncated version of email etc.) but the EmailBackend checks against the EMAIL in the db. the db does not have to be altered thus.

#

cornbread (on October 28, 2008):

How can we make it so there is no username field at all? We have 20,000 Users and they all use their emails currently. (making a switch to django)

#

peterbraden (on May 21, 2009):

This is good, but there is a problem - the authentication form limits usernames to 30 characters - emails longer than that are rejected by the charfield clean method. To properly allow for the (legitimate) case of emails longer than 30 characters the authentication views need to be overridden.

#

sijojamesjohn (on July 1, 2010):

In any models.py

from django.contrib.auth.forms import AuthenticationForm

AuthenticationForm.base_fields['username'].max_length = 75

#

starpilot (on December 11, 2010):

I'm a django neophyte, but it appears maintaining the username parameter is required to use the django.contrib.auth.views.login view. Could be wrong though.

#

cochiseruhulessin (on March 4, 2012):

"the field is only allowed to keep 30 characters, so you cann't just use munged email or md5 hash for username..."

A base64 encoding of an md5 hash has 25 characters.

#

kourosh (on June 19, 2012):

Can someone do a review and propose the best solution? thanks

#

(Forgotten your password?)