Can't login from django admin with custom user model

Hey guys.

I made a custom user model like this:

from django.contrib.auth.models import AbstractUser , BaseUserManager
from django.db import models

class CustomUserManager(BaseUserManager):
    use_in_migrations: bool = True

    def _create_user(self , email : str ,number : int,password : str , **kwargs) -> "User":
        if not email:
            raise ValueError("User must have an email address.")
        if not number:
            raise ValueError("User must have an phone number.")
        user : "User" = self.model(
            email = self.normalize_email(email),
            number=number,
            **kwargs
        )
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self , email , number , password , **kwargs):
        kwargs.setdefault('is_active', True)
        kwargs.setdefault('is_staff', False)
        kwargs.setdefault('is_superuser', False)
        return self._create_user(email=email,number=number, password=password, **kwargs)

    def create_superuser(self , email ,number , password , **kwargs):
        kwargs.setdefault('is_active', True)
        kwargs.setdefault('is_staff', True)
        kwargs.setdefault('is_superuser', True)
        if kwargs.get('is_staff') is not True:
            raise ValueError(
                'Superuser must have is_staff=True.'
            )
        if kwargs.get('is_superuser') is not True:
            raise ValueError(
                'Superuser must have is_superuser=True.'
            )
        return self._create_user(email=email,number=number, password=password, **kwargs)

class User(AbstractUser):
    username = None
    email = models.EmailField(unique=True)
    number = models.CharField(max_length=12, unique= True)
    email_verified = models.BooleanField(default=False)
    number_verified = models.BooleanField(default=False)
    objects = CustomUserManager()

    USERNAME_FIELD: str = 'email'
    REQUIRED_FIELDS: list[str] = ['number']

    def __str__(self) -> str:
        return self.email

and this is my custom authenticate backend

from django.contrib.auth.backends import BaseBackend
from django.contrib.auth import get_user_model

class EmailBackend(BaseBackend):
    model = get_user_model()
    def authenticate(
        self, request = None, email=None, password=None):
        try:
            user = self.model.objects.get(email=email)
        except self.model.DoesNotExist:
            return None
        if self.model.check_password(password) and user is not None:
            return user

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

Everything works fine while I try to log in from a view like this and after this, I can access the admin page. :

def index(request):
    username = 'myemail@gmail.com'
    password = 'mypassword'
    user = authenticate(request , email = username , password=  password)
    if user:
        login(request , user) # login is always successful
        return HttpResponse('Login')
    return HttpResponse('something')

but when I try to login from Django admin login form it doesn’t work
Screenshot from 2022-06-07 14-09-15

1 Like

I fixed this problem.
solution :
I’ve added the default django authentication backend to AUTHENTICATION_BACKENDS
Before it was like this :

AUTHENTICATION_BACKENDS = [
    'users.authback.EmailBackend',
]

And after that it’s like this :

AUTHENTICATION_BACKENDS = [
    'users.authback.EmailBackend',
    "django.contrib.auth.backends.ModelBackend", # this line fixed my problem
]
1 Like