I have the following User model which uses email as USERNAME_FIELD and leave the actual username unused.
All authentication features work fine, but I just realized I cannot create superuser with manage.py because of the error: create_superuser() missing 1 required positional argument: 'username'
Can anyone help me debug this error?
users/models.py
class User(AbstractUser):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
username = None
first_name = models.CharField(max_length=100, default="unknown")
last_name = models.CharField(max_length=100, default="unknown")
profile_pic = models.CharField(max_length=200, default="unknown")
premium = models.BooleanField(default=False)
email = models.EmailField(unique=True, db_index=True)
secret_key = models.CharField(max_length=255, default=get_random_secret_key)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = []
class Meta:
swappable = "AUTH_USER_MODEL"
users/services.py
def user_create(email, password=None, **extra_fields) -> User:
extra_fields = {"is_staff": False, "is_superuser": False, **extra_fields}
user = User(email=email, **extra_fields)
if password:
user.set_password(password)
else:
user.set_unusable_password()
user.full_clean()
user.save()
return user
def user_create_superuser(email, password=None, **extra_fields) -> User:
extra_fields = {**extra_fields, "is_staff": True, "is_superuser": True}
user = user_create(email=email, password=password, **extra_fields)
return user
@transaction.atomic
def user_get_or_create(
*, email: str, first_name: str, last_name: str, profile_pic: str
) -> Tuple[User, bool]:
user = User.objects.filter(email=email).first()
if user:
return user, False
return (
user_create(
email=email,
first_name=first_name,
last_name=last_name,
profile_pic=profile_pic,
),
True,
)
Full error log
❯ docker-compose run --rm web ./manage.py createsuperuser ─╯
Email: [email protected]
Password:
Password (again):
Traceback (most recent call last):
File "./manage.py", line 30, in <module>
main()
File "./manage.py", line 26, in main
execute_from_command_line(sys.argv)
File "/usr/local/lib/python3.8/site-packages/django/core/management/__init__.py", line 425, in execute_from_command_line
utility.execute()
File "/usr/local/lib/python3.8/site-packages/django/core/management/__init__.py", line 419, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/lib/python3.8/site-packages/django/core/management/base.py", line 373, in run_from_argv
self.execute(*args, **cmd_options)
File "/usr/local/lib/python3.8/site-packages/django/contrib/auth/management/commands/createsuperuser.py", line 79, in execute
return super().execute(*args, **options)
File "/usr/local/lib/python3.8/site-packages/django/core/management/base.py", line 417, in execute
output = self.handle(*args, **options)
File "/usr/local/lib/python3.8/site-packages/django/contrib/auth/management/commands/createsuperuser.py", line 195, in handle
self.UserModel._default_manager.db_manager(database).create_superuser(**user_data)
TypeError: create_superuser() missing 1 required positional argument: 'username'
CodePudding user response:
create_superuser
may not work for the customer User Model. You may implement the BaseUserManager
to do that.
class CustomerManager(BaseUserManager):
def create_superuser(self, email, password):
# create superuser here
...
here is the official document.
CodePudding user response:
I solved this issue by adding this custom UserManager. Thank you Allen, Adam, and Ghazi!
class UserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
extra_fields = {"is_staff": False, "is_superuser": False, **extra_fields}
if not email:
raise ValueError("Users must have an email address")
user = User(email=email, **extra_fields)
if password:
user.set_password(password)
else:
user.set_unusable_password()
return user
def create_superuser(self, email, password=None, **extra_fields):
extra_fields = {**extra_fields, "is_staff": True, "is_superuser": True}
user = self.create_user(email=email, password=password, **extra_fields)
return user