Custom User Model and Manager ( Django REST Framework )
Tags: django, webdev, beginners
Published: 2020-06-14 20:58:42

In the following post we will create a Custom User Model and a Custom User Manager for our Django Project.

Django provides a default User Model but the makers of the same **suggest that one should create a custom User Model** whenever starting a new project.

Custom User Model in Django gives you immense power to tackle the authentication part of your product, cater it to your own needs anytime.

After tinkering over numerous ways on how to go with it, here's a working solution **(most of the use cases tackled)**.

---

###We have used the following example

* We will extend the **_AbstractBaseUser_** class DRF provides us with. (though you might have heard about OneToOne Field and AbstractUser, I would suggest go with this approach)

* We will use **_email field as our username_**

* We make email, first name, last name and password **_mandatory fields_** (change accordingly to your needs)

* We created **_authentication_** app which takes care of all our project's authentication functionalities

---

**_Steps to follow_**
1. Create a CustomUserManager class
2. Create a CustomUser class
3. Update your _settings.py_ file

---
###Step 1 : Create a CustomUserManager class

In your **_authentication/models.py_** file - 

```python
class CustomUserManager(BaseUserManager):
    def create_user(self, email, first_name, last_name, password=None):
        if not email:
            raise ValueError("User must have an email")
        if not password:
            raise ValueError("User must have a password")
        if not first_name:
            raise ValueError("User must have a first name")
        if not last_name:
            raise ValueError("User must have a last name")

        user = self.model(
            email=self.normalize_email(email)
        )
        user.first_name = first_name
        user.last_name = last_name
        user.set_password(password)  # change password to hash
        user.is_admin = False
        user.is_staff = False
        user.save(using=self._db)
        return user

    def create_superuser(self, email, first_name, last_name, password=None):
        if not email:
            raise ValueError("User must have an email")
        if not password:
            raise ValueError("User must have a password")
        if not first_name:
            raise ValueError("User must have a first name")
        if not last_name:
            raise ValueError("User must have a last name")

        user = self.model(
            email=self.normalize_email(email)
        )
        user.first_name = first_name
        user.last_name = last_name
        user.set_password(password)  # change password to hash
        user.is_admin = True
        user.is_staff = True
        user.save(using=self._db)
        return user

    def create_staffuser(self, email, first_name, last_name,  password=None):
        if not email:
            raise ValueError("User must have an email")
        if not password:
            raise ValueError("User must have a password")
        if not first_name:
            raise ValueError("User must have a first name")
        if not last_name:
            raise ValueError("User must have a last name")

        user = self.model(
            email=self.normalize_email(email)
        )
        user.first_name = first_name
        user.last_name = last_name
        user.set_password(password)  # change password to hash
        user.is_admin = False
        user.is_staff = True
        user.save(using=self._db)
        return user

```
Now the next step is to create custom User Model

###Step 2 : Create a CustomUser class

In your **_authentication/models.py_** file - **after** CustomUserManager class

```python
class CustomUser(AbstractBaseUser):
    ADMIN = 'admin'
    STAFF = 'staff'
    STATUS = [
        (ADMIN, _('Admin User')),
        (STAFF, _('Staff User')),
    ]
    email = models.EmailField(_('email address'), unique=True)
    first_name = models.CharField(_('first name'), max_length=30)
    last_name = models.CharField(_('last name'), max_length=30)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)  # a admin user; non super-user
    is_admin = models.BooleanField(default=False)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name']

    objects = CustomUserManager()

    @staticmethod
    def has_perm(perm, obj=None):
        # "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

    @staticmethod
    def has_module_perms(app_label):
        # "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True

    def __str__(self):
        return "{}".format(self.email)

```

###Step 3 : Update your settings.py file

In your **_settings..py_** file add

```python
AUTH_USER_MODEL = 'authentication.CustomUser' # authentication is the app name
```

---
1. **_Please don't forget to migrate the models before creating users :)_**
2. **_Please don't forget to use the CustomUser Model while writing you views :)_**