DEV Community

Documendous
Documendous

Posted on

πŸ” How to Use Email as the Username in Django (The Right Way)

Using email instead of a username for login is more user-friendly and often preferred in modern applications. Django supports this, but it requires a custom user model. Here's how to set it up cleanly and correctly.


βœ… Step 1: Create a Custom User Model

In your core/models.py (or any appropriate app), define a user model using AbstractBaseUser and PermissionsMixin:

from django.contrib.auth.models import (
    AbstractBaseUser,
    BaseUserManager,
    PermissionsMixin,
)
from django.db import models

class UserManager(BaseUserManager):
    def create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError("Email is required")
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save()
        return user

    def create_superuser(self, email, password=None, **extra_fields):
        extra_fields.setdefault("is_staff", True)
        extra_fields.setdefault("is_superuser", True)
        return self.create_user(email, password, **extra_fields)

class AppUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    full_name = models.CharField(max_length=150)
    phone_number = models.CharField(max_length=20, blank=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    objects = UserManager()

    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = ["full_name"]

    def __str__(self):
        return self.email
Enter fullscreen mode Exit fullscreen mode

βœ… Step 2: Point Django to Your New User Model

In settings.py:

AUTH_USER_MODEL = "core.AppUser"
Enter fullscreen mode Exit fullscreen mode

Make sure this is set before running any migrations.


βœ… Step 3: Create and Apply Migrations

python manage.py makemigrations core
python manage.py migrate
Enter fullscreen mode Exit fullscreen mode

This sets up your database using the email field as the login ID.


βœ… Step 4: Use get_user_model() Everywhere

Avoid importing User directly. Use this in views, tests, and signals:

from django.contrib.auth import get_user_model

User = get_user_model()
Enter fullscreen mode Exit fullscreen mode

Example usage in tests:

User.objects.create_user(email="user@example.com", password="testpass")
Enter fullscreen mode Exit fullscreen mode

βœ… Step 5: Create Superuser with Email

When creating a superuser via script or CLI, use:

python manage.py createsuperuser --email admin@example.com --full_name "Admin"
Enter fullscreen mode Exit fullscreen mode

If you use --noinput, pass in the --email and --full_name values explicitly in your script.


βœ… Done

You now have a Django project where email is the unique identifier for login. This setup is clean, minimal, and aligns with real-world authentication flows.

Top comments (0)