createsuperuser.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. """
  2. Management utility to create superusers.
  3. """
  4. from __future__ import unicode_literals
  5. import getpass
  6. import sys
  7. from optparse import make_option
  8. from django.contrib.auth import get_user_model
  9. from django.contrib.auth.management import get_default_username
  10. from django.core import exceptions
  11. from django.core.management.base import BaseCommand, CommandError
  12. from django.db import DEFAULT_DB_ALIAS
  13. from django.utils.encoding import force_str
  14. from django.utils.six.moves import input
  15. from django.utils.text import capfirst
  16. class NotRunningInTTYException(Exception):
  17. pass
  18. class Command(BaseCommand):
  19. def __init__(self, *args, **kwargs):
  20. # Options are defined in an __init__ method to support swapping out
  21. # custom user models in tests.
  22. super(Command, self).__init__(*args, **kwargs)
  23. self.UserModel = get_user_model()
  24. self.username_field = self.UserModel._meta.get_field(self.UserModel.USERNAME_FIELD)
  25. self.option_list = BaseCommand.option_list + (
  26. make_option('--%s' % self.UserModel.USERNAME_FIELD, dest=self.UserModel.USERNAME_FIELD, default=None,
  27. help='Specifies the login for the superuser.'),
  28. make_option('--noinput', action='store_false', dest='interactive', default=True,
  29. help=('Tells Django to NOT prompt the user for input of any kind. '
  30. 'You must use --%s with --noinput, along with an option for '
  31. 'any other required field. Superusers created with --noinput will '
  32. ' not be able to log in until they\'re given a valid password.' %
  33. self.UserModel.USERNAME_FIELD)),
  34. make_option('--database', action='store', dest='database',
  35. default=DEFAULT_DB_ALIAS, help='Specifies the database to use. Default is "default".'),
  36. ) + tuple(
  37. make_option('--%s' % field, dest=field, default=None,
  38. help='Specifies the %s for the superuser.' % field)
  39. for field in self.UserModel.REQUIRED_FIELDS
  40. )
  41. option_list = BaseCommand.option_list
  42. help = 'Used to create a superuser.'
  43. def execute(self, *args, **options):
  44. self.stdin = options.get('stdin', sys.stdin) # Used for testing
  45. return super(Command, self).execute(*args, **options)
  46. def handle(self, *args, **options):
  47. username = options.get(self.UserModel.USERNAME_FIELD, None)
  48. interactive = options.get('interactive')
  49. verbosity = int(options.get('verbosity', 1))
  50. database = options.get('database')
  51. # If not provided, create the user with an unusable password
  52. password = None
  53. user_data = {}
  54. # Do quick and dirty validation if --noinput
  55. if not interactive:
  56. try:
  57. if not username:
  58. raise CommandError("You must use --%s with --noinput." %
  59. self.UserModel.USERNAME_FIELD)
  60. username = self.username_field.clean(username, None)
  61. for field_name in self.UserModel.REQUIRED_FIELDS:
  62. if options.get(field_name):
  63. field = self.UserModel._meta.get_field(field_name)
  64. user_data[field_name] = field.clean(options[field_name], None)
  65. else:
  66. raise CommandError("You must use --%s with --noinput." % field_name)
  67. except exceptions.ValidationError as e:
  68. raise CommandError('; '.join(e.messages))
  69. else:
  70. # Prompt for username/password, and any other required fields.
  71. # Enclose this whole thing in a try/except to trap for a
  72. # keyboard interrupt and exit gracefully.
  73. default_username = get_default_username()
  74. try:
  75. if hasattr(self.stdin, 'isatty') and not self.stdin.isatty():
  76. raise NotRunningInTTYException("Not running in a TTY")
  77. # Get a username
  78. verbose_field_name = self.username_field.verbose_name
  79. while username is None:
  80. if not username:
  81. input_msg = capfirst(verbose_field_name)
  82. if default_username:
  83. input_msg = "%s (leave blank to use '%s')" % (
  84. input_msg, default_username)
  85. raw_value = input(force_str('%s: ' % input_msg))
  86. if default_username and raw_value == '':
  87. raw_value = default_username
  88. try:
  89. username = self.username_field.clean(raw_value, None)
  90. except exceptions.ValidationError as e:
  91. self.stderr.write("Error: %s" % '; '.join(e.messages))
  92. username = None
  93. continue
  94. try:
  95. self.UserModel._default_manager.db_manager(database).get_by_natural_key(username)
  96. except self.UserModel.DoesNotExist:
  97. pass
  98. else:
  99. self.stderr.write("Error: That %s is already taken." %
  100. verbose_field_name)
  101. username = None
  102. for field_name in self.UserModel.REQUIRED_FIELDS:
  103. field = self.UserModel._meta.get_field(field_name)
  104. user_data[field_name] = options.get(field_name)
  105. while user_data[field_name] is None:
  106. raw_value = input(force_str('%s: ' % capfirst(field.verbose_name)))
  107. try:
  108. user_data[field_name] = field.clean(raw_value, None)
  109. except exceptions.ValidationError as e:
  110. self.stderr.write("Error: %s" % '; '.join(e.messages))
  111. user_data[field_name] = None
  112. # Get a password
  113. while password is None:
  114. if not password:
  115. password = getpass.getpass()
  116. password2 = getpass.getpass(force_str('Password (again): '))
  117. if password != password2:
  118. self.stderr.write("Error: Your passwords didn't match.")
  119. password = None
  120. continue
  121. if password.strip() == '':
  122. self.stderr.write("Error: Blank passwords aren't allowed.")
  123. password = None
  124. continue
  125. except KeyboardInterrupt:
  126. self.stderr.write("\nOperation cancelled.")
  127. sys.exit(1)
  128. except NotRunningInTTYException:
  129. self.stdout.write(
  130. "Superuser creation skipped due to not running in a TTY. "
  131. "You can run `manage.py createsuperuser` in your project "
  132. "to create one manually."
  133. )
  134. if username:
  135. user_data[self.UserModel.USERNAME_FIELD] = username
  136. user_data['password'] = password
  137. self.UserModel._default_manager.db_manager(database).create_superuser(**user_data)
  138. if verbosity >= 1:
  139. self.stdout.write("Superuser created successfully.")