Accepting email address as username in Django Accepting email address as username in Django python python

Accepting email address as username in Django


For anyone else wanting to do this, I'd recommend taking a look at django-email-as-username which is a pretty comprehensive solution, that includes patching up the admin and the createsuperuser management commands, amongst other bits and pieces.

Edit: As of Django 1.5 onwards you should consider using a custom user model instead of django-email-as-username.


Here's what we do. It isn't a "complete" solution, but it does much of what you're looking for.

from django import formsfrom django.contrib import adminfrom django.contrib.auth.admin import UserAdminfrom django.contrib.auth.models import Userclass UserForm(forms.ModelForm):    class Meta:        model = User        exclude = ('email',)    username = forms.EmailField(max_length=64,                                help_text="The person's email address.")    def clean_email(self):        email = self.cleaned_data['username']        return emailclass UserAdmin(UserAdmin):    form = UserForm    list_display = ('email', 'first_name', 'last_name', 'is_staff')    list_filter = ('is_staff',)    search_fields = ('email',)admin.site.unregister(User)admin.site.register(User, UserAdmin)


Here is one way to do it so that both username and email are accepted:

from django.contrib.auth.forms import AuthenticationFormfrom django.contrib.auth.models import Userfrom django.core.exceptions import ObjectDoesNotExistfrom django.forms import ValidationErrorclass EmailAuthenticationForm(AuthenticationForm):    def clean_username(self):        username = self.data['username']        if '@' in username:            try:                username = User.objects.get(email=username).username            except ObjectDoesNotExist:                raise ValidationError(                    self.error_messages['invalid_login'],                    code='invalid_login',                    params={'username':self.username_field.verbose_name},                )        return username

Don't know if there is some setting to set the default Authentication form but you can also override the url in urls.py

url(r'^accounts/login/$', 'django.contrib.auth.views.login', { 'authentication_form': EmailAuthenticationForm }, name='login'),

Raising the ValidationError will prevent 500 errors when an invalid email is submitted. Using the super's definition for "invalid_login" keeps the error message ambiguous (vs a specific "no user by that email found") which would be required to prevent leaking whether an email address is signed up for an account on your service. If that information is not secure in your architecture it might be friendlier to have a more informative error message.