Multiple USERNAME_FIELD users in django user model

My 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 log in via email as well as username?

+6
source share
5 answers

USERNAME_FIELD does not support the list. You can create a custom authentication server that tries to find the user in the "email" or "username" fields.

 from django.db.models import Q 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 server:

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

Please note that this solution is not perfect. For example, resetting the password will only work with the field specified in the USERNAME_FIELD setting.

+6
source

We can do this by implementing our own email authentication server.

You can do something like below:

Step 1 Adjust the user model of the user in the settings:

Since we would not use the Django default User model for authentication, we need to define our user model MyUser in settings.py . Set MyUser as AUTH_USER_MODEL in the project settings.

 AUTH_USER_MODEL = 'myapp.MyUser' 

Step-2 Write down the logic for your own authentication server:

To write our own authentication server, we need to implement at least two methods, i.e. get_user(user_id) and authenticate(**credentials) .

 from django.contrib.auth import get_user_model from django.contrib.auth.models import check_password class MyEmailBackend(object): """ Custom Email Backend to perform authentication via email """ def authenticate(self, username=None, password=None): my_user_model = get_user_model() try: user = my_user_model.objects.get(email=username) if user.check_password(password): return user # return user on valid credentials except my_user_model.DoesNotExist: return None # return None if custom user model does not exist except: return None # return None in case of other exceptions def get_user(self, user_id): my_user_model = get_user_model() try: return my_user_model.objects.get(pk=user_id) except my_user_model.DoesNotExist: return None 

Step-3 Specify your own authentication server in the settings:

After writing your own authentication backend, specify this authentication server in the AUTHENTICATION_BACKENDS setting.

AUTHENTICATION_BACKENDS contains a list of servers used for authentication. Django tries to authenticate with all of its authentication servers. If the first authentication method fails, Django tries to execute the second, etc., until all the backends are attempted.

 AUTHENTICATION_BACKENDS = ( 'my_app.backends.MyEmailBackend', # our custom authentication backend 'django.contrib.auth.backends.ModelBackend' # fallback to default authentication backend if first fails ) 

If authentication with MyEmailBackend fails, i.e. the user cannot be authenticated via email , we use the default authentication Django ModelBackend , which will try to authenticate through the username field of the MyUser model.

+6
source

No, you cannot have more than one field defined in USERNAME_FIELD .

One option is to write your own user login to check both fields yourself. https://docs.djangoproject.com/en/1.8/topics/auth/customizing/

i.e. change the backend to your own. AUTHENTICATION_BACKENDS then write the authentication method and check the username in both fields in the database.

PS you can use unique_together on your model so that there are no problems.

Another option is to use the actual username field to store both the string and email.

+2
source

Unfortunately, not out of the box.

The auth contrib module claims that the value of USERNAME_FIELD is unique.

See https://github.com/django/django/search?q=USERNAME_FIELD

If you want to have a multi-valued USERNAME_FIELD, you will either have to write the appropriate logic or find a package that will allow this.

0
source

If your USERNAME_FIELD username is and the user logs in with email , you can probably write a code that retrieves username using the provided email , and then use this username along with password for authentication.

0
source

All Articles