How to customize the superuser creation in Django when using a proper User model?

Question:

I have the following models defined on my user’s app:

class Address(models.Model):
    tower = models.SmallIntegerField()
    floor = models.SmallIntegerField()
    door = models.CharField(max_length=5)


class User(AbstractUser):
    address = models.OneToOneField(Address, on_delete=models.CASCADE)
    REQUIRED_FIELDS = ["email", "address"]

That is, I’m extending the Django’s base User object, by adding a one to one field to a table which handles the address for each user.

But taking this approach, then when I try to create a superuser account from CLI, with python manage.py createsuperuser, the following happens:

Username: admin
Email address: [email protected]
Address (Address.id): 1
Error: address instance with id 1 does not exist.

So Django is requesting me to enter an address id but as no address is yet stored in the database, that error is raised.

Is there any way to create a superuser by entering both fields from User model and from Address model, and creating a record in both tables? That is, something like:

Username: admin
Email address: [email protected]
Tower: 1
Floor: 12
Door: A
Asked By: Dani

||

Answers:

You should make your own command to create super user(customized)

/user/management/commands/createmysuperuser.py

from user.models import User, Address 
 from django.core.management import BaseCommand, CommandParser 
  
  
class Command(BaseCommand):
    help = 'create super user with address'

    def handle(self, *args, **options):
        username = input("Username: ")
        email = input("Email address:")
        tower = input("Tower:")
        floor = input("Floor:")
        door = input("Door:")

        address = Address.objects.create(...)
        user = User.objects.create(...)
        user.is_staff = True
        user.is_superuser = True
        user.save()
        
Answered By: Jaewoo Pyo

You can also override createsuperuser.

  1. Create a file managers.py:
from django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import gettext as _
from django.conf import settings

class CustomUserManager(BaseUserManager):
    """
    see https://dev.to/earthcomfy/getting-started-custom-user-model-5hc
    Custom user model manager where email is the unique identifier
    for authentication instead of usernames.
    """

    def create_user(self, email, password, **extra_fields):
        if not email:
            raise ValueError(_('Users must have an email address'))
        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, **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(email, password, **extra_fields)
  1. Within your user.models.py:
  • from .managers import CustomUserManager()
  • within your custom User class, include the line objects = CustomUserManager()
Answered By: dr_cornelius
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.