Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using email instead of login name in django

Firstly, this is not the question how to authenticate on email/password pair, but rather how to produce logical, and if you like, beautiful data structure.

I want to use emails as user names in a given django project. However, I am unable to re-use fields provided by auth.User model for at least two reasons:

  1. auth.User.username 's field max_length is 30 characters, which might not be enough for some email addresses.

  2. auth.User.email is not unique - which is obviously not satisfactory for a prerequisite saying that user names have to be unique.

So an obvious way here is to store username in a custom profile, which is linked to auth.User. In this case we have to deal with following problems:

  1. Generate unique username for auth.User.username - md5 hash of email should be fine here?
  2. Leave out completely auth.User.email empty - since it's only 75 characters long, while according to RFC 5321 (What is the maximum length of a valid email address?) email can be as long as 256 characters.

The following problems stem from the proposed solution:

  1. One is not going to be able to reuse built-in views/templates for standard operations like password reset etc
  2. In case of email change auth.User.username will have to be updated

To add oil into the fire, django developers are not likely to fix this limitation in any foreseeable future - see http://code.djangoproject.com/ticket/11365

So the question is: is there any other way to do it and do you see any other drawbacks in the solution proposed above?

Thanks!

like image 576
Art Avatar asked Feb 17 '10 22:02

Art


People also ask

How do I authenticate using email in Django?

Email authentication for Django 3.x For using email/username and password for authentication instead of the default username and password authentication, we need to override two methods of ModelBackend class: authenticate() and get_user():

How do I make email field unique in user model Django?

You have to declare the email field in your AbstractBaseUser model as unique=True . @mogoli Remove your db and migrations. In settings.py, add AUTH_USER_MODEL='new_user_model. MyUser'.

Is username in Django unique?

Even though the username field is marked as unique, by default it is not case-sensitive.


3 Answers

I had a client with a commercial site that had been up since 1995 (yeah, we're talking early adopters here). Anyway, they already had an established user base and the names were totally non-compliant with Django's idea of a username.

I looked at a few ways to handle it and they all felt like hacks (this was Summer of 2007), so I said screw it and hacked contrib.auth.models.User directly. I only had to change about 10 lines of code, increase the field size, and tweak the validator. We've done two upgrades since then -- 0.97-pre => 1.0, and 1.0 => 1.1.1 -- and it's only taken about 15 minutes each time to "port the hack".

It isn't pretty, and I may burn in Hell for doing it like this, but it took less time to do it this way than anything else I could figure out and the forward ports have been a total non-issue.

like image 92
Peter Rowell Avatar answered Oct 11 '22 11:10

Peter Rowell


You might want to take a look at how Satchmo handle this problem :

http://bitbucket.org/chris1610/satchmo/src/tip/satchmo/apps/satchmo_store/accounts/email-auth.py

and

http://bitbucket.org/chris1610/satchmo/src/533a63f955f8/satchmo/apps/satchmo_utils/unique_id.py

like image 31
kemar Avatar answered Oct 11 '22 10:10

kemar


I wrote up an explanation of my solution to this same problem: Django Authentication using an Email Address. It basically consists of:

  • Create a custom authorization backend for email authentication.
  • Subclass the user creation form to add email address as a required field.
  • Hide the username field from the user in the creation and login forms.
  • Randomly generate a username in the view that processes the creation form.
  • Manually ad a unique index to the email column (Yuck!)

My solution has still has 2 problems. First, manually creating a database index is not good. Second, the email is still limited to the 75 characters (I didn't have any issues porting a system with about 8,000 users). But, it plays pretty nicely with the rest of Django and 3rd party apps.

like image 40
Micah Carrick Avatar answered Oct 11 '22 11:10

Micah Carrick