Django does not create superuser using Custom User Model

Question:

I am creating a Django application and I am implementing a Custom User Model for authentication. I cannot create a superuser. I get an error saying RecursionError: maximum recursion depth exceeded while calling a Python object. I am using Django version 4.1.2.

Here is my User Model

class CustomAccountManager(BaseUserManager):
    def create_superuser(self, user_name, email, first_name, last_name, phone, password, **other_fields):

        other_fields.setdefault('is_staff', True)
        other_fields.setdefault('is_superuser', True)
        other_fields.setdefault('is_active', True)

        if other_fields.get('is_staff') is not True:
            raise ValueError(
                'Superuser must be assigned to is_staff=True.')
        if other_fields.get('is_superuser') is not True:
            raise ValueError(
                'Superuser must be assigned to is_superuser=True.')

        return self.create_superuser(email=email, user_name=user_name, first_name=first_name, last_name=last_name,
                                     phone=phone, password=password, **other_fields)

    def create_user(self, user_name, email, first_name, last_name, phone, password, **other_fields):

        if not email:
            return TypeError(_('Please provide an email address'))

        email = self.normalize_email(email)
        user = self.model(email=email, user_name=user_name, first_name=first_name, last_name=last_name, phone=phone,
                          **other_fields)
        user.set_password(password)
        user.save()

        return user


class Users(AbstractBaseUser, PermissionsMixin):
    id = models.AutoField(primary_key=True)
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    user_name = models.CharField(max_length=100, unique=True)
    email = models.EmailField(_('email address'), max_length=50, unique=True)
    phone = models.CharField(_('phone number'), max_length=50, unique=True)
    status = models.CharField(max_length=50)
    role_id = models.ForeignKey("Roles", on_delete=models.CASCADE, null=True)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    objects = CustomAccountManager()

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

    class Meta:
        ordering = ['id']

    def __str__(self):
        return self.user_name

Here is the error

Traceback (most recent call last):
  File "/Users/value8/Dev/Code/django/realtor/realtors/manage.py", line 22, in <module>
    main()
  File "/Users/value8/Dev/Code/django/realtor/realtors/manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/Users/value8/Dev/Code/django/realtor/.venv/lib/python3.10/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
    utility.execute()
  File "/Users/value8/Dev/Code/django/realtor/.venv/lib/python3.10/site-packages/django/core/management/__init__.py", line 440, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Users/value8/Dev/Code/django/realtor/.venv/lib/python3.10/site-packages/django/core/management/base.py", line 402, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/Users/value8/Dev/Code/django/realtor/.venv/lib/python3.10/site-packages/django/contrib/auth/management/commands/createsuperuser.py", line 88, in execute
    return super().execute(*args, **options)
  File "/Users/value8/Dev/Code/django/realtor/.venv/lib/python3.10/site-packages/django/core/management/base.py", line 448, in execute
    output = self.handle(*args, **options)
  File "/Users/value8/Dev/Code/django/realtor/.venv/lib/python3.10/site-packages/django/contrib/auth/management/commands/createsuperuser.py", line 233, in handle
    self.UserModel._default_manager.db_manager(database).create_superuser(
  File "/Users/value8/Dev/Code/django/realtor/realtors/backend/models.py", line 24, in create_superuser
    return self.create_superuser(email=email, user_name=user_name, first_name=first_name, last_name=last_name,
  File "/Users/value8/Dev/Code/django/realtor/realtors/backend/models.py", line 24, in create_superuser
    return self.create_superuser(email=email, user_name=user_name, first_name=first_name, last_name=last_name,
  File "/Users/value8/Dev/Code/django/realtor/realtors/backend/models.py", line 24, in create_superuser
    return self.create_superuser(email=email, user_name=user_name, first_name=first_name, last_name=last_name,
  [Previous line repeated 988 more times]
  File "/Users/value8/Dev/Code/django/realtor/realtors/backend/models.py", line 13, in create_superuser
    other_fields.setdefault('is_staff', True)
RecursionError: maximum recursion depth exceeded while calling a Python object

How can I fix it

Asked By: Kevnlan

||

Answers:

You are calling the function create_superuser recursively:

class CustomAccountManager(BaseUserManager):
    def create_superuser(self, user_name, email, first_name, last_name, phone, password, **other_fields):

        other_fields.setdefault('is_staff', True)
        other_fields.setdefault('is_superuser', True)
        other_fields.setdefault('is_active', True)

        if other_fields.get('is_staff') is not True:
            raise ValueError(
                'Superuser must be assigned to is_staff=True.')
        if other_fields.get('is_superuser') is not True:
            raise ValueError(
                'Superuser must be assigned to is_superuser=True.')

        # You are calling the function from within 
        return self.create_superuser(email=email, user_name=user_name, first_name=first_name, last_name=last_name,
                                     phone=phone, password=password, **other_fields)

Here’s how django does it :

    def create_superuser(self, username, email=None, password=None, **extra_fields):
            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(username, email, password, **extra_fields)
Answered By: Mike Jones
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.