Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple USERNAME_FIELD in django user model

My custom user model:

class MyUser(AbstractBaseUser):
    username = models.CharField(unique=True,max_length=30)
    email = models.EmailField(unique=True,max_length=75)
    is_staff = models.IntegerField(default=False)
    is_active = models.IntegerField(default=False)
    date_joined = models.DateTimeField(default=None)

    # Use default usermanager
    objects = UserManager()

    USERNAME_FIELD = 'email'

Is there a way to specify multiple USERNAME_FIELD ? Something like ['email','username'] so that users can login via email as well as username ?

like image 617
Saurabh Verma Avatar asked Jul 12 '15 16:07

Saurabh Verma


People also ask

What is Auth_user_model in Django?

Django allows you to override the default user model by providing a value for the AUTH_USER_MODEL setting that references a custom model. Method 2 – AUTH_USER_MODEL : AUTH_USER_MODEL is the recommended approach when referring to a user model in a models.py file.

How do you extend User models?

Extending the existing User model If you wish to store information related to User , you can use a one-to-one relationship to a model containing the fields for additional information. This one-to-one model is often called a profile model, as it might store non-auth related information about a site user.

What is UserAdmin in Django?

Django uses UserAdmin to render the nice admin look for User model. By just using this in our admin.py -file, we can get the same look for our model. from django.contrib.auth.admin import UserAdmin admin.site.register(MyUser, UserAdmin)


1 Answers

The USERNAME_FIELD setting does not support a list. You could create a custom authentication backend that tries to look up the user on the 'email' or 'username' fields.

from django.db.models import Q

from django.contrib.auth import get_user_model

MyUser = get_user_model()

class UsernameOrEmailBackend(object):
    def authenticate(self, username=None, password=None, **kwargs):
        try:
           # Try to fetch the user by searching the username or email field
            user = MyUser.objects.get(Q(username=username)|Q(email=username))
            if user.check_password(password):
                return user
        except MyUser.DoesNotExist:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a non-existing user (#20760).
            MyUser().set_password(password)

Then, in your settings.py set AUTHENTICATION_BACKENDS to your authentication backend:

 AUTHENTICATION_BACKENDS = ('path.to.UsernameOrEmailBackend,)\

Note that this solution isn't perfect. For example, password resets would only work with the field specified in your USERNAME_FIELD setting.

like image 181
Alasdair Avatar answered Sep 19 '22 11:09

Alasdair