Loading django/contrib/auth/management/commands/createsuperuser.py +48 −42 Original line number Diff line number Diff line Loading @@ -16,50 +16,56 @@ from django.utils.text import capfirst class Command(BaseCommand): option_list = BaseCommand.option_list + ( make_option('--username', dest='username', default=None, help='Specifies the username for the superuser.'), def __init__(self, *args, **kwargs): # Options are defined in an __init__ method to support swapping out # custom user models in tests. super(Command, self).__init__(*args, **kwargs) self.UserModel = get_user_model() self.username_field = self.UserModel._meta.get_field(self.UserModel.USERNAME_FIELD) self.option_list = BaseCommand.option_list + ( make_option('--%s' % self.UserModel.USERNAME_FIELD, dest=self.UserModel.USERNAME_FIELD, default=None, help='Specifies the login for the superuser.'), make_option('--noinput', action='store_false', dest='interactive', default=True, help=('Tells Django to NOT prompt the user for input of any kind. ' 'You must use --username with --noinput, along with an option for ' 'You must use --%s with --noinput, along with an option for ' 'any other required field. Superusers created with --noinput will ' ' not be able to log in until they\'re given a valid password.')), ' not be able to log in until they\'re given a valid password.' % self.UserModel.USERNAME_FIELD)), make_option('--database', action='store', dest='database', default=DEFAULT_DB_ALIAS, help='Specifies the database to use. Default is "default".'), ) + tuple( make_option('--%s' % field, dest=field, default=None, help='Specifies the %s for the superuser.' % field) for field in get_user_model().REQUIRED_FIELDS for field in self.UserModel.REQUIRED_FIELDS ) option_list = BaseCommand.option_list help = 'Used to create a superuser.' def handle(self, *args, **options): username = options.get('username', None) username = options.get(self.UserModel.USERNAME_FIELD, None) interactive = options.get('interactive') verbosity = int(options.get('verbosity', 1)) database = options.get('database') UserModel = get_user_model() username_field = UserModel._meta.get_field(UserModel.USERNAME_FIELD) other_fields = UserModel.REQUIRED_FIELDS # If not provided, create the user with an unusable password password = None other_data = {} user_data = {} # Do quick and dirty validation if --noinput if not interactive: try: if not username: raise CommandError("You must use --username with --noinput.") username = username_field.clean(username, None) raise CommandError("You must use --%s with --noinput." % self.UserModel.USERNAME_FIELD) username = self.username_field.clean(username, None) for field_name in other_fields: for field_name in self.UserModel.REQUIRED_FIELDS: if options.get(field_name): field = UserModel._meta.get_field(field_name) other_data[field_name] = field.clean(options[field_name], None) field = self.UserModel._meta.get_field(field_name) user_data[field_name] = field.clean(options[field_name], None) else: raise CommandError("You must use --%s with --noinput." % field_name) except exceptions.ValidationError as e: Loading @@ -74,9 +80,8 @@ class Command(BaseCommand): # Get a username while username is None: username_field = UserModel._meta.get_field(UserModel.USERNAME_FIELD) if not username: input_msg = capfirst(username_field.verbose_name) input_msg = capfirst(self.username_field.verbose_name) if default_username: input_msg += " (leave blank to use '%s')" % default_username raw_value = input(input_msg + ': ') Loading @@ -84,31 +89,30 @@ class Command(BaseCommand): if default_username and raw_value == '': raw_value = default_username try: username = username_field.clean(raw_value, None) username = self.username_field.clean(raw_value, None) except exceptions.ValidationError as e: self.stderr.write("Error: %s" % '; '.join(e.messages)) username = None continue try: UserModel.objects.using(database).get(**{ UserModel.USERNAME_FIELD: username }) except UserModel.DoesNotExist: self.UserModel.objects.db_manager(database).get_by_natural_key(username) except self.UserModel.DoesNotExist: pass else: self.stderr.write("Error: That username is already taken.") self.stderr.write("Error: That %s is already taken." % self.username_field.verbose_name) username = None for field_name in other_fields: field = UserModel._meta.get_field(field_name) other_data[field_name] = options.get(field_name) while other_data[field_name] is None: for field_name in self.UserModel.REQUIRED_FIELDS: field = self.UserModel._meta.get_field(field_name) user_data[field_name] = options.get(field_name) while user_data[field_name] is None: raw_value = input(capfirst(field.verbose_name + ': ')) try: other_data[field_name] = field.clean(raw_value, None) user_data[field_name] = field.clean(raw_value, None) except exceptions.ValidationError as e: self.stderr.write("Error: %s" % '; '.join(e.messages)) other_data[field_name] = None user_data[field_name] = None # Get a password while password is None: Loading @@ -128,6 +132,8 @@ class Command(BaseCommand): self.stderr.write("\nOperation cancelled.") sys.exit(1) UserModel.objects.db_manager(database).create_superuser(username=username, password=password, **other_data) user_data[self.UserModel.USERNAME_FIELD] = username user_data['password'] = password self.UserModel.objects.db_manager(database).create_superuser(**user_data) if verbosity >= 1: self.stdout.write("Superuser created successfully.") django/contrib/auth/tests/custom_user.py +2 −2 Original line number Diff line number Diff line Loading @@ -23,8 +23,8 @@ class CustomUserManager(BaseUserManager): user.save(using=self._db) return user def create_superuser(self, username, password, date_of_birth): u = self.create_user(username, password=password, date_of_birth=date_of_birth) def create_superuser(self, email, password, date_of_birth): u = self.create_user(email, password=password, date_of_birth=date_of_birth) u.is_admin = True u.save(using=self._db) return u Loading django/contrib/auth/tests/management.py +1 −1 Original line number Diff line number Diff line Loading @@ -138,7 +138,7 @@ class CreatesuperuserManagementCommandTestCase(TestCase): new_io = StringIO() call_command("createsuperuser", interactive=False, username="joe@somewhere.org", email="joe@somewhere.org", date_of_birth="1976-04-01", stdout=new_io, skip_validation=True Loading docs/topics/auth.txt +60 −50 Original line number Diff line number Diff line Loading @@ -1878,6 +1878,8 @@ The easiest way to construct a compliant custom User model is to inherit from implementation of a `User` model, including hashed passwords and tokenized password resets. You must then provide some key implementation details: .. class:: models.CustomUser .. attribute:: User.USERNAME_FIELD A string describing the name of the field on the User model that is Loading @@ -1904,6 +1906,11 @@ password resets. You must then provide some key implementation details: ... REQUIRED_FIELDS = ['date_of_birth', 'height'] .. note:: ``REQUIRED_FIELDS`` must contain all required fields on your User model, but should *not* contain the ``USERNAME_FIELD``. .. method:: User.get_full_name(): A longer formal identifier for the user. A common interpretation Loading @@ -1918,7 +1925,7 @@ password resets. You must then provide some key implementation details: value as :meth:`django.contrib.auth.User.get_full_name()`. The following methods are available on any subclass of :class:`~django.contrib.auth.models.AbstractBaseUser`:: :class:`~django.contrib.auth.models.AbstractBaseUser`: .. class:: models.AbstractBaseUser Loading Loading @@ -1979,24 +1986,26 @@ defines different fields, you will need to define a custom manager that extends :class:`~django.contrib.auth.models.BaseUserManager` providing two additional methods: .. method:: UserManager.create_user(username, password=None, **other_fields) .. class:: models.CustomUserManager The prototype of `create_user()` should accept all required fields as arguments. For example, if your user model defines `username`, and `date_of_birth` as required fields, then create_user should be defined as:: .. method:: models.CustomUserManager.create_user(*username_field*, password=None, **other_fields) def create_user(self, username, date_of_birth, password=None): The prototype of `create_user()` should accept the username field, plus all required fields as arguments. For example, if your user model uses `email` as the username field, and has `date_of_birth` as a required fields, then create_user should be defined as:: def create_user(self, email, date_of_birth, password=None): # create user here .. method:: UserManager.create_superuser(username, password, **other_fields) .. method:: models.CustomUserManager.create_superuser(*username_field*, password, **other_fields) The prototype of `create_superuser()` should accept all required fields as arguments. For example, if your user model defines `username`, and `date_of_birth` as required fields, then create_user should be defined as:: The prototype of `create_user()` should accept the username field, plus all required fields as arguments. For example, if your user model uses `email` as the username field, and has `date_of_birth` as a required fields, then create_superuser should be defined as:: def create_superuser(self, username, date_of_birth, password): def create_superuser(self, email, date_of_birth, password): # create superuser here Unlike `create_user()`, `create_superuser()` *must* require the caller Loading @@ -2006,6 +2015,7 @@ additional methods: utility methods: .. class:: models.BaseUserManager .. method:: models.BaseUserManager.normalize_email(email) A classmethod that normalizes email addresses by lowercasing Loading Loading @@ -2165,12 +2175,12 @@ authentication app:: user.save(using=self._db) return user def create_superuser(self, username, date_of_birth, password): def create_superuser(self, email, date_of_birth, password): """ Creates and saves a superuser with the given email, date of birth and password. """ user = self.create_user(username, user = self.create_user(email, password=password, date_of_birth=date_of_birth ) Loading Loading @@ -2223,7 +2233,7 @@ authentication app:: return self.is_admin Then, to register this custom User model with Django's admin, the following code would be required in ``admin.py``:: code would be required in the app's ``admin.py`` file:: from django import forms from django.contrib import admin Loading @@ -2249,7 +2259,7 @@ code would be required in ``admin.py``:: password1 = self.cleaned_data.get("password1") password2 = self.cleaned_data.get("password2") if password1 and password2 and password1 != password2: raise forms.ValidationError('Passwords don't match') raise forms.ValidationError("Passwords don't match") return password2 def save(self, commit=True): Loading Loading
django/contrib/auth/management/commands/createsuperuser.py +48 −42 Original line number Diff line number Diff line Loading @@ -16,50 +16,56 @@ from django.utils.text import capfirst class Command(BaseCommand): option_list = BaseCommand.option_list + ( make_option('--username', dest='username', default=None, help='Specifies the username for the superuser.'), def __init__(self, *args, **kwargs): # Options are defined in an __init__ method to support swapping out # custom user models in tests. super(Command, self).__init__(*args, **kwargs) self.UserModel = get_user_model() self.username_field = self.UserModel._meta.get_field(self.UserModel.USERNAME_FIELD) self.option_list = BaseCommand.option_list + ( make_option('--%s' % self.UserModel.USERNAME_FIELD, dest=self.UserModel.USERNAME_FIELD, default=None, help='Specifies the login for the superuser.'), make_option('--noinput', action='store_false', dest='interactive', default=True, help=('Tells Django to NOT prompt the user for input of any kind. ' 'You must use --username with --noinput, along with an option for ' 'You must use --%s with --noinput, along with an option for ' 'any other required field. Superusers created with --noinput will ' ' not be able to log in until they\'re given a valid password.')), ' not be able to log in until they\'re given a valid password.' % self.UserModel.USERNAME_FIELD)), make_option('--database', action='store', dest='database', default=DEFAULT_DB_ALIAS, help='Specifies the database to use. Default is "default".'), ) + tuple( make_option('--%s' % field, dest=field, default=None, help='Specifies the %s for the superuser.' % field) for field in get_user_model().REQUIRED_FIELDS for field in self.UserModel.REQUIRED_FIELDS ) option_list = BaseCommand.option_list help = 'Used to create a superuser.' def handle(self, *args, **options): username = options.get('username', None) username = options.get(self.UserModel.USERNAME_FIELD, None) interactive = options.get('interactive') verbosity = int(options.get('verbosity', 1)) database = options.get('database') UserModel = get_user_model() username_field = UserModel._meta.get_field(UserModel.USERNAME_FIELD) other_fields = UserModel.REQUIRED_FIELDS # If not provided, create the user with an unusable password password = None other_data = {} user_data = {} # Do quick and dirty validation if --noinput if not interactive: try: if not username: raise CommandError("You must use --username with --noinput.") username = username_field.clean(username, None) raise CommandError("You must use --%s with --noinput." % self.UserModel.USERNAME_FIELD) username = self.username_field.clean(username, None) for field_name in other_fields: for field_name in self.UserModel.REQUIRED_FIELDS: if options.get(field_name): field = UserModel._meta.get_field(field_name) other_data[field_name] = field.clean(options[field_name], None) field = self.UserModel._meta.get_field(field_name) user_data[field_name] = field.clean(options[field_name], None) else: raise CommandError("You must use --%s with --noinput." % field_name) except exceptions.ValidationError as e: Loading @@ -74,9 +80,8 @@ class Command(BaseCommand): # Get a username while username is None: username_field = UserModel._meta.get_field(UserModel.USERNAME_FIELD) if not username: input_msg = capfirst(username_field.verbose_name) input_msg = capfirst(self.username_field.verbose_name) if default_username: input_msg += " (leave blank to use '%s')" % default_username raw_value = input(input_msg + ': ') Loading @@ -84,31 +89,30 @@ class Command(BaseCommand): if default_username and raw_value == '': raw_value = default_username try: username = username_field.clean(raw_value, None) username = self.username_field.clean(raw_value, None) except exceptions.ValidationError as e: self.stderr.write("Error: %s" % '; '.join(e.messages)) username = None continue try: UserModel.objects.using(database).get(**{ UserModel.USERNAME_FIELD: username }) except UserModel.DoesNotExist: self.UserModel.objects.db_manager(database).get_by_natural_key(username) except self.UserModel.DoesNotExist: pass else: self.stderr.write("Error: That username is already taken.") self.stderr.write("Error: That %s is already taken." % self.username_field.verbose_name) username = None for field_name in other_fields: field = UserModel._meta.get_field(field_name) other_data[field_name] = options.get(field_name) while other_data[field_name] is None: for field_name in self.UserModel.REQUIRED_FIELDS: field = self.UserModel._meta.get_field(field_name) user_data[field_name] = options.get(field_name) while user_data[field_name] is None: raw_value = input(capfirst(field.verbose_name + ': ')) try: other_data[field_name] = field.clean(raw_value, None) user_data[field_name] = field.clean(raw_value, None) except exceptions.ValidationError as e: self.stderr.write("Error: %s" % '; '.join(e.messages)) other_data[field_name] = None user_data[field_name] = None # Get a password while password is None: Loading @@ -128,6 +132,8 @@ class Command(BaseCommand): self.stderr.write("\nOperation cancelled.") sys.exit(1) UserModel.objects.db_manager(database).create_superuser(username=username, password=password, **other_data) user_data[self.UserModel.USERNAME_FIELD] = username user_data['password'] = password self.UserModel.objects.db_manager(database).create_superuser(**user_data) if verbosity >= 1: self.stdout.write("Superuser created successfully.")
django/contrib/auth/tests/custom_user.py +2 −2 Original line number Diff line number Diff line Loading @@ -23,8 +23,8 @@ class CustomUserManager(BaseUserManager): user.save(using=self._db) return user def create_superuser(self, username, password, date_of_birth): u = self.create_user(username, password=password, date_of_birth=date_of_birth) def create_superuser(self, email, password, date_of_birth): u = self.create_user(email, password=password, date_of_birth=date_of_birth) u.is_admin = True u.save(using=self._db) return u Loading
django/contrib/auth/tests/management.py +1 −1 Original line number Diff line number Diff line Loading @@ -138,7 +138,7 @@ class CreatesuperuserManagementCommandTestCase(TestCase): new_io = StringIO() call_command("createsuperuser", interactive=False, username="joe@somewhere.org", email="joe@somewhere.org", date_of_birth="1976-04-01", stdout=new_io, skip_validation=True Loading
docs/topics/auth.txt +60 −50 Original line number Diff line number Diff line Loading @@ -1878,6 +1878,8 @@ The easiest way to construct a compliant custom User model is to inherit from implementation of a `User` model, including hashed passwords and tokenized password resets. You must then provide some key implementation details: .. class:: models.CustomUser .. attribute:: User.USERNAME_FIELD A string describing the name of the field on the User model that is Loading @@ -1904,6 +1906,11 @@ password resets. You must then provide some key implementation details: ... REQUIRED_FIELDS = ['date_of_birth', 'height'] .. note:: ``REQUIRED_FIELDS`` must contain all required fields on your User model, but should *not* contain the ``USERNAME_FIELD``. .. method:: User.get_full_name(): A longer formal identifier for the user. A common interpretation Loading @@ -1918,7 +1925,7 @@ password resets. You must then provide some key implementation details: value as :meth:`django.contrib.auth.User.get_full_name()`. The following methods are available on any subclass of :class:`~django.contrib.auth.models.AbstractBaseUser`:: :class:`~django.contrib.auth.models.AbstractBaseUser`: .. class:: models.AbstractBaseUser Loading Loading @@ -1979,24 +1986,26 @@ defines different fields, you will need to define a custom manager that extends :class:`~django.contrib.auth.models.BaseUserManager` providing two additional methods: .. method:: UserManager.create_user(username, password=None, **other_fields) .. class:: models.CustomUserManager The prototype of `create_user()` should accept all required fields as arguments. For example, if your user model defines `username`, and `date_of_birth` as required fields, then create_user should be defined as:: .. method:: models.CustomUserManager.create_user(*username_field*, password=None, **other_fields) def create_user(self, username, date_of_birth, password=None): The prototype of `create_user()` should accept the username field, plus all required fields as arguments. For example, if your user model uses `email` as the username field, and has `date_of_birth` as a required fields, then create_user should be defined as:: def create_user(self, email, date_of_birth, password=None): # create user here .. method:: UserManager.create_superuser(username, password, **other_fields) .. method:: models.CustomUserManager.create_superuser(*username_field*, password, **other_fields) The prototype of `create_superuser()` should accept all required fields as arguments. For example, if your user model defines `username`, and `date_of_birth` as required fields, then create_user should be defined as:: The prototype of `create_user()` should accept the username field, plus all required fields as arguments. For example, if your user model uses `email` as the username field, and has `date_of_birth` as a required fields, then create_superuser should be defined as:: def create_superuser(self, username, date_of_birth, password): def create_superuser(self, email, date_of_birth, password): # create superuser here Unlike `create_user()`, `create_superuser()` *must* require the caller Loading @@ -2006,6 +2015,7 @@ additional methods: utility methods: .. class:: models.BaseUserManager .. method:: models.BaseUserManager.normalize_email(email) A classmethod that normalizes email addresses by lowercasing Loading Loading @@ -2165,12 +2175,12 @@ authentication app:: user.save(using=self._db) return user def create_superuser(self, username, date_of_birth, password): def create_superuser(self, email, date_of_birth, password): """ Creates and saves a superuser with the given email, date of birth and password. """ user = self.create_user(username, user = self.create_user(email, password=password, date_of_birth=date_of_birth ) Loading Loading @@ -2223,7 +2233,7 @@ authentication app:: return self.is_admin Then, to register this custom User model with Django's admin, the following code would be required in ``admin.py``:: code would be required in the app's ``admin.py`` file:: from django import forms from django.contrib import admin Loading @@ -2249,7 +2259,7 @@ code would be required in ``admin.py``:: password1 = self.cleaned_data.get("password1") password2 = self.cleaned_data.get("password2") if password1 and password2 and password1 != password2: raise forms.ValidationError('Passwords don't match') raise forms.ValidationError("Passwords don't match") return password2 def save(self, commit=True): Loading