0

I thought it would be a breeze to swap the User model's username with its email. So I am using a CustomUser.

from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils.translation import ugettext_lazy as _
from .managers import UserManager

class CustomUser(AbstractUser):
    """User model."""

    username = None
    email = models.EmailField(_('email address'), unique=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = UserManager()

Since CustomUser is inherited from AbstractUser model, I thought I was done, but I guess I am still far from it.

Here's my django shell interaction:

>> from django.contrib.auth import get_user_model
>> User = get_user_model()
>> User.objects.create(email='dave@gmail.com', password='123')                                                                                                                                        
   <CustomUser: dave@gmail.com> 
>> User.objects.get(email='dave@gmail.com').password
   '123' # wutt? why is this plaintext?
>> User.objects.get(email='dave@gmail.com').set_password('abc')
>> User.objects.get(email='dave@gmail.com').password
   '123' # still same!

So functionally, this is completely useless. Since django.contrib.auth.authenticate for the users always returns None. What am I doing wrong? How can I achieve the minimal functionality that my CustomUser is only different from default django User model in that my CustomUser should use email as the username?

I have already checked out the SO hits:

Django User password not getting hashed for custom users

django custom user model password is not being hashed

EDIT: I'm using the following as my UserManager

from django.contrib.auth.models import BaseUserManager

class UserManager(BaseUserManager):
    """Define a model manager for User model with no username field."""

    use_in_migrations = True

    def _create_user(self, email, password, **extra_fields):
        """Create and save a User with the given email and password."""
        if not email:
            raise ValueError('The given email must be set')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password=None, **extra_fields):
        """Create and save a regular User with the given email and password."""
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email, password, **extra_fields):
        """Create and save a SuperUser with the given email and password."""
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        return self._create_user(email, password, **extra_fields)
DaveIdito
  • 1,546
  • 14
  • 31
  • How do you register / create your users? Also `set_password` does not save the user so naturally `User.objects.get(email='dave@gmail.com').set_password('abc')` would not change anything. Try something like `user = User.objects.get(email='dave@gmail.com')` then `user.set_password('abc')` and then `user.save()`. – Abdul Aziz Barkat Apr 03 '21 at 12:05

1 Answers1

1

You use User.objects.create(email='dave@gmail.com', password='123') to create your user. .create() does not take into consideration that the password needs to be hashed (it is a normal method provided by all models). Instead use .create_user():

User.objects.create_user(email='dave@gmail.com', password='123')

Also you try to set the users password by writing:

User.objects.get(email='dave@gmail.com').set_password('abc')

This does not work because set_password does not save anything to the database. You should do this instead:

user = User.objects.get(email='dave@gmail.com')
user.set_password('abc')
user.save()
Abdul Aziz Barkat
  • 19,475
  • 3
  • 20
  • 33