1

I was trying to implement registration for 3 types of users: Parent, School and Vendor.

from django.db import models
from django.contrib.auth.models import (AbstractBaseUser, BaseUserManager)

class UserManager(BaseUserManager):
    def create_user(self, email, password=None, is_staff=False, is_admin=False, is_active=True, is_parent=False, is_school=False, is_vendor=False):
        if not email:
            raise ValueError("Users must have an email address")
        if not password:
            raise ValueError("Users must have a password")
        if not parent:
            raise ValueError("Users must have a role")
        if not school:
            raise ValueError("Users must have a role")
        if not vendor:
            raise ValueError("Users must have a role")

        user_obj = self.model(
            email = self.normalize_email(email)
        )
        user_obj.set_password(password) # change user password
        user_obj.parent = is_parent
        user_obj.school = is_school
        user_obj.vendor = is_vendor
        user_obj.active = is_active
        user_obj.staff = is_staff
        user_obj.admin = is_admin
        user_obj.save(using=self._db)
        return user_obj

    def create_parentuser(self, parent, school, vendor, email, password=None):
        user = self.create_user(
                email,
                parent,
                school,
                vendor,
                password=password,
                is_parent=True
        )
        return user

    def create_schooluser(self, email, parent, school, vendor, password=None):
        user = self.create_user(
                email,
                parent,
                school,
                vendor,
                password=password,
                is_school=True
        )
        return user

    def create_vendoruser(self, email, parent, school, vendor, password=None):
        user = self.create_user(
                email,
                parent,
                school,
                vendor,
                password=password,
                is_vendor=True
        )
        return user

    def create_staffuser(self, parent, school, vendor, email, password=None):
        user = self.create_user(
                email,
                parent,
                school,
                vendor,
                password=password,
                is_staff=True
        )
        return user

    def create_superuser(self, email, parent, school, vendor, password=None):
        user = self.create_user(
                email,
                parent,
                school,
                vendor,
                password=password,
                is_staff=True,
                is_admin=True,
        )
        user.set_password(password)
        return user

class User(AbstractBaseUser):
    email       = models.EmailField(max_length=255, unique=True)
    active      = models.BooleanField(default=True) # can login 
    parent      = models.BooleanField(default=False) # parent user
    school      = models.BooleanField(default=False) # school admin user
    vendor      = models.BooleanField(default=False) # vendor user  
    staff       = models.BooleanField(default=False) # staff user non superuser
    admin       = models.BooleanField(default=False) # superuser 
    timestamp   = models.DateTimeField(auto_now_add=True)
    
    USERNAME_FIELD = 'email' # username

    REQUIRED_FIELDS = ['parent', 'school', 'vendor' ]

    objects = UserManager()

    def __str__(self):
        return self.email

    def get_full_name(self):
        return self.email

    def get_short_name(self):
        return self.email

    def has_perm(self, perm, obj=None):
        return True

    def has_module_perms(self, app_label):
        return True

    @property
    def is_parent(self):
        return self.parent

    @property
    def is_school(self):
        return self.school
        
    @property
    def is_vendor(self):
        return self.vendor

    @property
    def is_active(self):
        return self.active

    @property
    def is_staff(self):
        return self.staff

    @property
    def is_admin(self):
        return self.admin

I have followed a tutorial logic and do not understand some of the parts. Probably you can suggest a better way. However, it works and I can create 3 users by checking the checkbox. But I can't create a superuser. The system asks me for 'Email', 'Parent', 'School', 'Vendor' and password as I have 3 required fields. At the end the Error message appears:

File "/home/azamat/dev/dj_test/src/accounts/models.py", line 79, in create_superuser user = self.create_user( TypeError: create_user() got multiple values for argument 'password'

So how to create a superuser to access the admin dashboard?

Riyas Ac
  • 1,553
  • 1
  • 9
  • 23

3 Answers3

2

Your create_user() has defined the password as its 2nd parameter, so when you call self.create_user(email, parent, password=password), you are basically passing password two times there, once as a positional parameter, second time as a named parameter.

Pass everything either as named parameters (eg. password=password) or as positional parameters.

yedpodtrzitko
  • 9,035
  • 2
  • 40
  • 42
  • Sorry not clear what should I do. I have changed everything to named parameters **user = self.create_user(parent=parent, school=school, vendor=vendor, email=email, password=password)** which gives **File "/home/azamat/dev/dj_test/src/accounts/models.py", line 79, in create_superuser user = self.create_user( TypeError: create_user() got an unexpected keyword argument 'parent'** – Azamat Uzbekov Aug 19 '20 at 03:54
  • if I do user = self.create_user( parent, school, vendor, email, password ) I receive File "/home/azamat/dev/dj_test/src/accounts/models.py", line 11, in create_user raise ValueError("Users must have an email address") ValueError: Users must have an email address – Azamat Uzbekov Aug 19 '20 at 04:13
  • @AzamatUzbekov it's telling you *exactly* what is wrong there. I can just repeat it in different words, but I dont know how else make it clear: you are passing `parent` parameter to your `create_user()` but the method does not have `parent` parameter in its signature. – yedpodtrzitko Aug 19 '20 at 06:16
  • ok. I added **parent, school, vendor** to my _def create_user_. it worked! thanks. – Azamat Uzbekov Aug 19 '20 at 19:23
0

Here we use extra_fields to pass more parameters.Your parameter password is defined 2nd position but you call other position. I simply change the code as given below.

Please try this:

from django.db import models
from django.contrib.auth.models import (AbstractBaseUser, BaseUserManager)

class UserManager(BaseUserManager):
    def create_user(self, email, password=None,**extra_fields):
        if not email:
            raise ValueError("Users must have an email address")
        if not password:
            raise ValueError("Users must have a password")
        if extra_fields.get('is_parent') is not True:
            raise ValueError("Users must have a role")
        if extra_fields.get('is_school') is not True:
            raise ValueError("Users must have a role")
        if extra_fields.get('is_vendor') is not True:
            raise ValueError("Users must have a role")

        user_obj = self.model(
            email = self.normalize_email(email)
        **extra_fields
        )
        user_obj.set_password(password) # change user password
        user_obj.save(using=self._db)
        return user_obj

    def create_parentuser(self, email,password, **extra_fields):
        user = self.create_user(
            email = email,
            password=password,
        )
        extra_fields.setdefault('is_school', False)
        extra_fields.setdefault('is_parent', True)
        extra_fields.setdefault('is_vendor', False)
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        extra_fields.setdefault('is_active', True)

        if extra_fields.get('is_parent') 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.')
        user.save(using=self._db)
        return user
    def create_schooluser(self, email,password, **extra_fields):
        user = self.create_user(
            email = email,
            password=password,
        )
        extra_fields.setdefault('is_school', True)
        extra_fields.setdefault('is_parent', False)
        extra_fields.setdefault('is_vendor', False)
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        extra_fields.setdefault('is_active', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Users must have a role')
        user.save(using=self._db)
        return user

    def create_vendoruser(self, email,password, **extra_fields):
        user = self.create_user(
            email = email,
            password=password,
        )
        extra_fields.setdefault('is_school', False)
        extra_fields.setdefault('is_parent', False)
        extra_fields.setdefault('is_vendor', True)
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        extra_fields.setdefault('is_active', True)

        if extra_fields.get('is_vendor') is not True:
            raise ValueError('Users must have a role')
        user.save(using=self._db)
        return user

    def create_staffuser(self, email,password, **extra_fields):
        user = self.create_user(
            email = email,
            password=password,
        )
        extra_fields.setdefault('is_school', False)
        extra_fields.setdefault('is_parent', False)
        extra_fields.setdefault('is_vendor', False)
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', False)
        extra_fields.setdefault('is_active', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Users must have a role')
        user.save(using=self._db)
        return user

    def create_superuser(self, email,password, **extra_fields):
        user = self.create_user(
            email = email,
            password=password,
        )
        extra_fields.setdefault('is_school', True)
        extra_fields.setdefault('is_parent', True)
        extra_fields.setdefault('is_vendor', True)
        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.')
        user.is_admin = True
        user.is_superuser = True
        user.save(using=self._db)
        return user
Riyas Ac
  • 1,553
  • 1
  • 9
  • 23
  • Copypasted your solution and got an error: **File "/home/azamat/dev/dj_test/src/accounts/models.py", line 15, in create_user raise ValueError("Users must have a role") ValueError: Users must have a role** – Azamat Uzbekov Aug 19 '20 at 03:45
  • `extra_fields = {} extra_fields['is_school'] = True extra_fields['is_parent'] = True extra_fields['is_vendor'] = True extra_fields['is_staff'] = True extra_fields['is_superuser'] = True extra_fields['is_active'] = True User.objects.create_user(email='test@test.com',password='top_secret',**extra_fields)` – Riyas Ac Aug 19 '20 at 04:20
0

Remove set_password() in create_superuser() function definition.

# code before

    def create_superuser(self, email, password):
        user = self.create_user(
                email,
                password,
                is_staff=True,
                is_admin=True,
        )
        return user

# code after

In-order to create a superuser all you need is email, password, is_staff and is_admin as per create_user() function definition.

As you have passed is_staff and is_admin as keyword arguments in create_user() which is in create_superuser() you need only email and password as arguments for create_superuser().

Like wise: in create_user() definition named arguments have been defined. So, it is not necessary that they are to be passed everytime we call the function.

While calling create_user() only required arguments are to be passed according to the user role. Other arguments can be neglected.

class UserManager(BaseUserManager):
    def create_user(self, email, password, is_staff=False, is_admin=False, is_active=True, is_parent=False, is_school=False, is_vendor=False):
        if not email:
            raise ValueError("Users must have an email address")
        if not password:
            raise ValueError("Users must have a password")
        if not is_parent and not is_school and not is_vendor:
            raise ValueError("Users must have a role")

        user_obj = self.model(
            email = self.normalize_email(email)
        )
        user_obj.set_password(password) # change user password
        user_obj.parent = is_parent
        user_obj.school = is_school
        user_obj.vendor = is_vendor
        user_obj.active = is_active
        user_obj.staff = is_staff
        user_obj.admin = is_admin
        user_obj.save(using=self._db)
        return user_obj

    def create_parentuser(self, email, password=None):
        user = self.create_user(
                email,
                password,
                is_parent=is_parent
        )
        return user

    def create_schooluser(self, email, password=None):
        user = self.create_user(
                email,
                password,
                is_school=True
        )
        return user

    def create_vendoruser(self, email, password=None):
        user = self.create_user(
                email,
                password,
                is_vendor=True
        )
        return user

    def create_staffuser(self, email, password=None, is_staff=True):
        user = self.create_user(
                email,
                password,
                is_staff=True
        )
        return user

    def create_superuser(self, email, password ):
        user = self.create_user(
                email,
                password,
                is_staff=True,
                is_admin=True,
                is_parent=True,
                is_school=True,
                is_vendor=True
        )
        return user
Achuth Varghese
  • 2,356
  • 1
  • 4
  • 18