[Django]-Using email as username with django

1👍

You have to modify the username length field so that syncdb will create the proper length varchar and you also have to modify the AuthenticationForm to allow greater values as well or else your users won’t be able to log in.

from django.contrib.auth.forms import AuthenticationForm

AuthenticationForm.base_fields['username'].max_length = 150
AuthenticationForm.base_fields['username'].widget.attrs['maxlength'] = 150
AuthenticationForm.base_fields['username'].validators[0].limit_value = 150

2👍

I’ve had to modify the auth_user table by hand to make the field longer and then convert emails into a username by removing the @ symbol and the period (maybe other characters too, it’s really not a great solution). Then, you have to write a custom auth backend that authenticates a user based on their email, not the username, since you just need to store the username to appease django.

In other words, don’t use the username field for auth anymore, use the email field and just store the username as a version of the email to make Django happy.

Their official response on this topic is that many sites prefer usernames for auth. It really depends if you are making a social site or just a private site for users.

👤Max

2👍

If you override the form for Django users you can actually pull this off pretty gracefully.

class CustomUserCreationForm(UserCreationForm):
"""
    The form that handles our custom user creation
    Currently this is only used by the admin, but it 

would make sense to allow users to register on their own later
“””
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)

class Meta:
    model = User
    fields = ('first_name','last_name','email')

and then in your backends.py you could put

class EmailAsUsernameBackend(ModelBackend):
"""
Try to log the user in treating given username as email.
We do not want superusers here as well
"""

def authenticate(self, username, password):
    try:
        user = User.objects.get(email=username)
        if user.check_password(password):
            if user.is_superuser():
                pass
            else: return user

    except User.DoesNotExist: return None

then in your admin.py you could override with

class UserCreationForm(CustomUserCreationForm):
"""
    This overrides django's requirements on creating a user

    We only need email, first_name, last_name
    We're going to email the password
"""
def __init__(self, *args, **kwargs):
    super(UserCreationForm, self).__init__(*args, **kwargs)
    # let's require these fields
    self.fields['email'].required       = True
    self.fields['first_name'].required  = True
    self.fields['last_name'].required   = True
    # let's not require these since we're going to send a reset email to start their account
    self.fields['username'].required    = False
    self.fields['password1'].required   = False
    self.fields['password2'].required   = False

Mine has a few other modifications, but this should get you on the right track.

Leave a comment