Opened 5 years ago

Closed 5 years ago

#20541 closed Cleanup/optimization (fixed)

Differenciate user from superuser creation in django.contrib.auth at a signal level

Reported by: antonio@… Owned by: Anton Baklanov
Component: contrib.auth Version: 1.5
Severity: Normal Keywords:
Cc: antonbaklanov@… Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: yes UI/UX: no


Hi all,

Currently the steps to create a superuser (auth.models.User.create_superuser) are:

1) Create user
2) Save User
3) Assign staff, active, superuser
4) Save again

When the first save happens the post_save signal is raised, but the user is not a superuser yet. The signal will get raised again after a few lines, which is wasteful. My proposal is to implement superuser creation like this:

class UserManager(BaseUserManager):

    def create_user(self, username, email=None, password=None, save=True, **extra_fields):
        Creates and saves a User with the given username, email and password.
        now =
        if not username:
            raise ValueError('The given username must be set')
        email = self.normalize_email(email)
        user = self.model(username=username, email=email,
                          is_staff=False, is_active=True, is_superuser=False,
                          last_login=now, date_joined=now, **extra_fields)

        if save:
        return user

    def create_superuser(self, username, email, password, **extra_fields):
        u = self.create_user(username, email, password, save=False, **extra_fields)
        u.is_staff = True
        u.is_active = True
        u.is_superuser = True
        return u

Now when post_save is fired, one can check is_superuser, is_staff or is_active and take action based on that.

Change History (3)

comment:1 Changed 5 years ago by Russell Keith-Magee

Triage Stage: UnreviewedAccepted

I fully accept that the underlying problem -- that saving a superuser involves 2 saves -- should be solved. I'm just not completely convinced about the solution. The extra save=True argument seems messy to me.

Personally, I'd rather see the 'guts' of create_user factored out into in internal method that is called by both create_user and create_superuser - that way, the public call to create_user would end up looking a lot like create_superuser, but with reversed boolean values.

comment:2 Changed 5 years ago by Anton Baklanov

Cc: antonbaklanov@… added
Owner: changed from nobody to Anton Baklanov
Status: newassigned

here is my pull request for this

comment:3 Changed 5 years ago by Tim Graham <timograham@…>

Resolution: fixed
Status: assignedclosed

In cab333cb16656cbb7d2bcfb06b2f7aeab9bac7af:

Fixed #20541 -- don't raise db signals twice when creating superuser

Note: See TracTickets for help on using tickets.
Back to Top