create superuser in django custom User model with phone number as username

Question:

I have a django project which I want it to have phone number as its username field. I’ve created an app named accounts, and this is the models.py:

class UserManager(BaseUserManager):
    use_in_migrations = True

    def create_user(self, phone_number, password, **extra_fields):
        user = self.model(phone_number=phone_number, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, phone_number, password, **extra_fields):
        extra_fields.setdefault("is_staff", True)
        extra_fields.setdefault("is_superuser", True)
        extra_fields.setdefault("is_active", 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(phone_number, password, **extra_fields)


class User(AbstractUser):
    phone_number = models.CharField(max_length=20, null=False, blank=False, unique=True)
    email = models.EmailField(max_length=100, blank=True, null=True)
    name = models.CharField(max_length=50)
    USERNAME_FIELD = "phone_number"
    username = None
    first_name = None
    last_name = None
    objects = UserManager()
    REQUIRED_FIELDS = [phone_number]

And I’ve declared it as my user model, in settings.py.

AUTH_USER_MODEL = "accounts.User"
ACCOUNT_USER_MODEL_USERNAME_FIELD = "phone_number"

When I run python manage.py createsuperuser, I get this error:

django.core.exceptions.FieldDoesNotExist: User has no field named 'accounts.User.phone_number'

I can’t figure out what is the problem.

This is the full error:

Traceback (most recent call last):
  File "/home/foo/.local/lib/python3.10/site-packages/django/db/models/options.py", line 668, in get_field
    return self.fields_map[field_name]
KeyError: <django.db.models.fields.CharField: phone_number>

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/foo/Desktop/custom/manage.py", line 22, in <module>
    main()
  File "/home/foo/Desktop/custom/manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/home/foo/.local/lib/python3.10/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
    utility.execute()
  File "/home/foo/.local/lib/python3.10/site-packages/django/core/management/__init__.py", line 440, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/foo/.local/lib/python3.10/site-packages/django/core/management/base.py", line 394, in run_from_argv
    parser = self.create_parser(argv[0], argv[1])
  File "/home/foo/.local/lib/python3.10/site-packages/django/core/management/base.py", line 357, in create_parser
    self.add_arguments(parser)
  File "/home/foo/.local/lib/python3.10/site-packages/django/contrib/auth/management/commands/createsuperuser.py", line 61, in add_arguments
    field = self.UserModel._meta.get_field(field_name)
  File "/home/foo/.local/lib/python3.10/site-packages/django/db/models/options.py", line 670, in get_field
    raise FieldDoesNotExist(
django.core.exceptions.FieldDoesNotExist: User has no field named 'accounts.User.phone_number'
Asked By: Tom

||

Answers:

Its very easy my friend just add the following to the user model

USERNAME_FIELD = 'phone_number'

Look at this answer to know more:
Django Login with Email or Phone Number

Answered By: Mahmoud Nasser

There were three problems in my code:

  1. technically setting username field to None must be done before declaring USERNAME_FIELD.
  2. REQUIRED_FIELDS itmes must be strings, not variables.
  3. phone_number shouldn’t be in REQUIRED_FIELDS, as it’s USERNAME_FIELD.

So my User model class would be like this:

class User(AbstractUser):
    username = None
    first_name = None
    last_name = None
    phone_number = models.CharField(max_length=20, null=False, blank=False, unique=True)
    email = models.EmailField(max_length=100, blank=True, null=True)
    name = models.CharField(max_length=50)
    USERNAME_FIELD = "phone_number"
    objects = UserManager()

Update

As Mahammadhusain mentioned, there is no need to pass ACCOUNT_USER_MODEL_USERNAME_FIELD in settings.py, as I’ve set USERNAME_FIELD in models.py

Answered By: Tom

No need pass USERNAME FIELD in settings.py you can pass explicitly USERNAME FIELD like this…


class User(AbstractUser):
    phone_number = models.CharField(max_length=20, null=False, blank=False, unique=True)
    email = models.EmailField(max_length=100, blank=True, null=True)
    name = models.CharField(max_length=50)
    username = None
    first_name = None
    last_name = None
    
    objects = UserManager()

    
    USERNAME_FIELD = 'phone_number'
    REQUIRED_FIELDS = ['email']

for batter understanding refer this link here