Django's built in authentication system requires the username to be alpha-numeric only. Therefore, email addresses are invalid. However, in many cases, you would like to use an email address as the username. This snippet allows you to do so. It has the added benefit that if you want to continue using the regular username format, you can do that too. It's the best of both worlds!
To make sure propoer credit is given, this code is modified from a django group posting from Vasily Sulatskov.
To use this file, save it in your project as something like: email-auth.py
Then, add the following lines to your settings.py file:
AUTHENTICATION_BACKENDS = ( 'yourproject.email-auth.EmailBackend', )
You can see a full implementation [here] (http://www.satchmoproject.com/trac/browser/satchmo/trunk/satchmo)
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
- Image compression before saving the new model / work with JPG, PNG by Schleidens 6 days, 4 hours ago
- Help text hyperlinks by sa2812 1 month ago
- Stuff by NixonDash 3 months, 1 week ago
- Add custom fields to the built-in Group model by jmoppel 5 months, 1 week ago
- Month / Year SelectDateWidget based on django SelectDateWidget by pierreben 8 months, 3 weeks ago
Does it works admin app? In my case not :)
This is certainly a useful snippet, but it seems a little over complicated. What's wrong with just:
...and then just adding it in front of Django's
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).
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
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...
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?
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", ) '
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?
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.
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.
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)
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.
In any models.py
from django.contrib.auth.forms import AuthenticationForm
AuthenticationForm.base_fields['username'].max_length = 75
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.
"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.
Can someone do a review and propose the best solution? thanks
Please login first before commenting.