Should I use "AbstractUser" or "AbstractBaseUser"? (Django)

Viewed 532

My requirement is to create AUTH system which uses email as AUTH token and some extra fields like name, phone etc and get rid of username field:

I can achieve this using both the abstract classes ! But confused on which to use

I can just use AbstractUser and make "username=None" and then add usernanager ! 
Or should i use AbstractBaseUser and redo everything ?
3 Answers

This answer exaplains it better which one to use. However it depends on a lot of things. In short :

Django uses authentication using username field by default. If you want to use an email address as your authentication instead of a username, then it is better to extend AbstractBaseUser. But, if you are happy with how django handle authentication but need some extra information on User model, then you can extend AbstractUser.

You also can check the documentation Using a custom user model when starting a project .

according to [Django Docs]:

If you’re entirely happy with Django’s User model, but you want to add some additional profile information, you could subclass django.contrib.auth.models.AbstractUser and add your custom profile fields, although we’d recommend a separate model as described in the “Model design considerations” note of Specifying a custom user model. AbstractUser provides the full implementation of the default User as an abstract model.

So i think you are not happy with AbstractUser and you want something different. so just use AbstractBaseUser and extend it as you wish.

Basically, you better use "AbstractUser" class instead of "AbstractBaseUser" class. Actually, using "AbstractUser" class or "AbstractBaseUser" class, you can do the same things such as adding and removing fields and so on. And actually, "AbstractUser" class is the subclass of "AbstractBaseUser" class and "AbstractUser" class has 11 fields which you will basically use as shown below:

id
password
last_login
is_superuser
username
first_name
last_name
email
is_staff
is_active
date_joined

But "AbstractBaseUser" class which is the superclass of "AbstractUser" class only has 3 fields which you will basically use as shown below:

id
password
last_login

So, when you create "CustomUser" class with "AbstractUser" class, you can write much less code defining less fields because "AbstractUser" class already has 8 more fields which you will basically use than "AbstractBaseUser" class.

For example, you want to log in with "email" and "password" instead of "username" and "password" so you create 2 "CustomUser" classes with "AbstractUser" class and "AbstractBaseUser" class as shown below:

<"AbstractUser" class>

# "models.py"

from django.db import models
from django.contrib.auth.models import AbstractUser
from .managers import CustomUserManager

class CustomUser(AbstractUser):
    username = None # Remove "username"
    email = models.EmailField('email address', unique=True)
    
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = CustomUserManager()

    class Meta:
        verbose_name = "custom user"
        verbose_name_plural = "custom users"

<"AbstractBaseUser" class>

# "models.py"

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.utils import timezone
from .managers import CustomUserManager

class CustomUser(AbstractBaseUser, PermissionsMixin):
    first_name = models.CharField("first name", max_length=150, blank=True)
    last_name = models.CharField("last name", max_length=150, blank=True)
    email = models.EmailField('email address', unique=True)
    is_staff = models.BooleanField(
        "staff status",
        default=False,
        help_text="Designates whether the user can log into this admin site.",
    )
    is_active = models.BooleanField(
        "active",
        default=True,
        help_text=
            "Designates whether this user should be treated as active. "
            "Unselect this instead of deleting accounts."
        ,
    )
    date_joined = models.DateTimeField("date joined", default=timezone.now)

    USERNAME_FIELD = 'email'

    objects = CustomUserManager() # Here

As you can see above, "CustomUser" class with "AbstractUser" class has much less code than the one with "AbstractBaseUser" class. That's why basically, you better use "AbstractUser" class instead of "AbstractBaseUser" class.

Related