For at least a year we have known that Django 1.5 would contain functionality to significantly alter the User model. For years, I thought I wanted to get rid of the Django User.username field and have email be the username. A few versions back, Django changed the username to allow the char @, which made it possible to put an email address in the username. Not a bad hack. I just modified the save method to copy the email into the username field. Now with Django 1.5 we don’t have to do that. But maybe I still want to…
Many years ago, I first considered using the email address as a username. I was motivated by the number of users who hand trouble logging in. A surprising number forgot their username. Email as username seemed like a good way to solve that problem. Not everyone was on board with this change. One objection was that some people share email addresses, thus they could not have individual accounts on our system. I think that problem is so rare, its worth ignoring. The other objection was that if there is something like a discussion board or messaging on the website, some users will not want their email displayed. This seems like a reasonable objection. Maybe even more so today.
So now that I can get rid of the User.username, I am not going to. With the exception of over-riding some of the methods, I am going to stick with the default Django User model.Since I am just over-riding methods, I will use a proxy model of User. Here’s how it will work:
When a new user is created, if a username is not specified, email address will be copied into the username field on save. Although its not completely DRY, this process will be done in forms because username is still a required field.Update: as of Django 1.5 the username is limited to 30 chars. Its not uncommon for a email address to exceed 30 chars. Thus not all usernames can be set to the email address. Thus is does not make sense to make any usernames be email addresses. I think the solution to this is to set the username to a unique random string.
- Users can edit their username to be whatever they want (but it still must be unique)
- I am using a custom authentication backend that allows users to login with either their username or email address. For more info, check out this blog post.
I was also considering adding some new fields to the User model, but the Django documentation convinced me to put those fields in another model with User as a foreign key. The reason for this is that User is a foreign key in lots of models. If you mess up a migration of User, lots of things will break. By putting those fields in another model, adding or removing fields is much less likely to break everything. This is similar to the UserProfile functionality in previous versions of Django. That functionality is deprecated in Django 1.5. With Django 1.5, this mechanism is normalized to be like any other one-to-one relationship.