How to Use Email as Username for Django Authentication.
Tags: django, python
Published: 2021-08-05 13:09:39

Django comes with a default user model that's used for the standard authentication system. If you had worked on Django you probably have seen this authentication page.

![Default Admin Log-in page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ptczfqlk38nuv2lyphpz.png)

We're going to override this model with our own custom model that allows us to use an `Email` instead of the standard `Username` that comes with the Django default model.

We're gonna modify `models.py` file to include our user profile model.
The first thing we need to do is import some additional classes at the top.

 **AbstractBaseUser** 

According to Django documentation `AbstractBaseUser` has the authentication functionality only , it has no actual fields, you will supply the fields to use when you subclass.

 **PermissionsMixin**

Django provides `PermissionsMixin`. This is an abstract model you can include in the class hierarchy for your user model, giving you all the methods and database fields necessary to support Django’s permission model.

 **BaseUserManager**

If your user model defines `username`, `email`, `is_staff`, `is_active`, `is_superuser`, `last_login`, and `date_joined` fields the same as Django’s default user, you can install Django’s `UserManager`; however, if your user model defines different fields, you’ll need to define a custom manager that extends `BaseUserManager`.

Add this lines at top of the file.

```
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.models import BaseUserManager
```

### Creating UserProfile Class.

Underneath the imports let's create a new class called `UserProfile` and inherit from the `AbstractBaseUser` and `PermissionsMixin`

```
class UserProfile(AbstractBaseUser, PermissionsMixin):
    """ Database model for users in the system """
    email = models.EmailField(max_length=255, unique=True)
    name = models.CharField(max_length=255)

    objects = UserProfileManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['name']

    def __str__(self):
        """ Return string representation of our user """
        return self.email
```
By adding above code we:

* Made the `email` and `name` field required and made `email` unique
* Set the `USERNAME_FIELD` which defines the unique identifier for the `username` to `email`.
* Specified that all objects for the class come from the `UserProfileManager`

### Creating UserProfileManager Class.

Now that we have our custom user model we can go ahead and create a manager. Now because we've customized our model we need to tell Django how to interact with this user model in order to create users because by default when it creates a user it expects a user name field and password field but we replace the user name field with an email field.So we just need to create a custom manager that can handle creating users with an email field instead of a user name field.
 
Let's create a new class called `UserProfileManager` and inherit from the `BaseUserManager`.
```
class UserProfileManager(BaseUserManager):
    """ Manager for user profiles """
```

`UserProfileManager` the way it manages work is you specify
some functions within the manager that can be used to manipulate objects within the module that the manager is for.

Below are two functions which we need to add in `UserProfileManager` class.

```
def create_user(self, email, name, password=None):
        """ Create a new user profile """
        if not email:
            raise ValueError('User must have an email address')

        email = self.normalize_email(email)
        user = self.model(email=email, name=name)

        user.set_password(password)
        user.save(using=self._db)

        return user

    def create_superuser(self, email, name, password):
        """ Create a new superuser profile """
        user = self.create_user(email,name, password)
        user.is_superuser = True
        user.is_staff = True

        user.save(using=self._db)

        return user
```
 
Above code sets logic for when one creates users and superusers using Django CLI.

### Update Settings to use Custom Model.

We need add below line in `settings.py` to use this model over default one.

```
AUTH_USER_MODEL = 'App_name.UserProfile'
```

### Make changes in Database.

Create new migrations and migrate them which will create a new database that uses our custom User Model:

```
$ python manage.py makemigrations
$ python manage.py migrate
```

### Create superuser

```
$ python manage.py createsuperuser
Email address: chokshiroshan@gmail.com
Password:
Password (again):
Superuser created successfully.
```

### Test

As you can see instead of asking for `Username` it is prompting for `Email`.

![Screenshot 2021-08-05 at 6.34.30 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/irs014xrigrw9zfxyxyy.png)