Is there any way to login to Django admin interface using username or email?

Question:

I want to implement a login system to login to Django admin via email or username. Does anyone know how to implement it. I use custom user model. I know how to allow user to login to website using username or email. But it doesn’t work in Django admin interface

from django.conf import settings
from django.contrib.auth import get_user_model


class EmailOrUsernameModelBackend(object):

    def authenticate(self, username=None, password=None):
        if '@' in username:
            kwargs = {'email': username}
        else:
            kwargs = {'username': username}
        try:
            user = get_user_model().objects.get(**kwargs)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            return None

    def get_user(self, username):
        try:
            return get_user_model().objects.get(pk=username)
        except get_user_model().DoesNotExist:
            return None
Asked By: Dizz

||

Answers:

You need to pass request in the authenticated method:

from django.conf import settings
from django.contrib.auth import get_user_model


class EmailOrUsernameModelBackend(object):

    def authenticate(self, request, username=None, password=None):
        if '@' in username:
            kwargs = {'email__iexact': username}
        else:
            kwargs = {'username': username}
        try:
            user = get_user_model().objects.get(**kwargs)
            if user.check_password(password):
                return user
        except get_user_model().DoesNotExist:
            return None

    def get_user(self, username):
        try:
            return get_user_model().objects.get(pk=username)
        except get_user_model().DoesNotExist:
            return None

Also, make sure to put it in AUTHENTICATION_BACKENDS:

AUTHENTICATION_BACKENDS = ['path.to.EmailOrUsernameModelBackend']
Answered By: ruddra

You could create a custom user manager sub-classing from the UserManager class and override the get_by_natural_key method.

from django.contrib.auth.models import UserManager

class UserAccountManager(UserManager):
    def get_by_natural_key(self, username):
        return self.get(
            models.Q(**{self.model.USERNAME_FIELD: username})
            | models.Q(**{self.model.EMAIL_FIELD: username})
        )

Please note that this will authenticate all users in your system by either email or password and not just on the admin page.

Answered By: Lewiskori