Fixed #5943 -- Modified django-admin to behave like manage.py if settings are provided, either as --settings or DJANGO_SETTINGS_MODULE. Thanks to Joseph Kocherhans and Todd O'Bryan for their work on this ticket.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@8282 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2008-08-10 08:42:49 +00:00
parent 7610983bb2
commit ec7d8b7c61
3 changed files with 70 additions and 69 deletions

View File

@ -66,7 +66,7 @@ def load_command_class(app_name, name):
return getattr(__import__('%s.management.commands.%s' % (app_name, name), return getattr(__import__('%s.management.commands.%s' % (app_name, name),
{}, {}, ['Command']), 'Command')() {}, {}, ['Command']), 'Command')()
def get_commands(load_user_commands=True, project_directory=None): def get_commands():
""" """
Returns a dictionary mapping command names to their callback applications. Returns a dictionary mapping command names to their callback applications.
@ -77,7 +77,7 @@ def get_commands(load_user_commands=True, project_directory=None):
Core commands are always included. If a settings module has been Core commands are always included. If a settings module has been
specified, user-defined commands will also be included, the specified, user-defined commands will also be included, the
startproject command will be disabled, and the startapp command startproject command will be disabled, and the startapp command
will be modified to use the directory in which that module appears. will be modified to use the directory in which the settings module appears.
The dictionary is in the format {command_name: app_name}. Key-value The dictionary is in the format {command_name: app_name}. Key-value
pairs from this dictionary can then be used in calls to pairs from this dictionary can then be used in calls to
@ -94,15 +94,28 @@ def get_commands(load_user_commands=True, project_directory=None):
if _commands is None: if _commands is None:
_commands = dict([(name, 'django.core') for name in find_commands(__path__[0])]) _commands = dict([(name, 'django.core') for name in find_commands(__path__[0])])
if load_user_commands: # Find the installed apps
# Get commands from all installed apps. try:
from django.conf import settings from django.conf import settings
for app_name in settings.INSTALLED_APPS: apps = settings.INSTALLED_APPS
try: except (AttributeError, EnvironmentError, ImportError):
path = find_management_module(app_name) apps = []
_commands.update(dict([(name, app_name) for name in find_commands(path)]))
except ImportError: # Find the project directory
pass # No management module -- ignore this app. try:
from django.conf import settings
project_directory = setup_environ(__import__(settings.SETTINGS_MODULE))
except (AttributeError, EnvironmentError, ImportError):
project_directory = None
# Find and load the management module for each installed app.
for app_name in apps:
try:
path = find_management_module(app_name)
_commands.update(dict([(name, app_name)
for name in find_commands(path)]))
except ImportError:
pass # No management module - ignore this app
if project_directory: if project_directory:
# Remove the "startproject" command from self.commands, because # Remove the "startproject" command from self.commands, because
@ -203,8 +216,6 @@ class ManagementUtility(object):
def __init__(self, argv=None): def __init__(self, argv=None):
self.argv = argv or sys.argv[:] self.argv = argv or sys.argv[:]
self.prog_name = os.path.basename(self.argv[0]) self.prog_name = os.path.basename(self.argv[0])
self.project_directory = None
self.user_commands = False
def main_help_text(self): def main_help_text(self):
""" """
@ -212,7 +223,7 @@ class ManagementUtility(object):
""" """
usage = ['',"Type '%s help <subcommand>' for help on a specific subcommand." % self.prog_name,''] usage = ['',"Type '%s help <subcommand>' for help on a specific subcommand." % self.prog_name,'']
usage.append('Available subcommands:') usage.append('Available subcommands:')
commands = get_commands(self.user_commands, self.project_directory).keys() commands = get_commands().keys()
commands.sort() commands.sort()
for cmd in commands: for cmd in commands:
usage.append(' %s' % cmd) usage.append(' %s' % cmd)
@ -225,7 +236,7 @@ class ManagementUtility(object):
"django-admin.py" or "manage.py") if it can't be found. "django-admin.py" or "manage.py") if it can't be found.
""" """
try: try:
app_name = get_commands(self.user_commands, self.project_directory)[subcommand] app_name = get_commands()[subcommand]
if isinstance(app_name, BaseCommand): if isinstance(app_name, BaseCommand):
# If the command is already loaded, use it directly. # If the command is already loaded, use it directly.
klass = app_name klass = app_name
@ -278,20 +289,6 @@ class ManagementUtility(object):
else: else:
self.fetch_command(subcommand).run_from_argv(self.argv) self.fetch_command(subcommand).run_from_argv(self.argv)
class ProjectManagementUtility(ManagementUtility):
"""
A ManagementUtility that is specific to a particular Django project.
As such, its commands are slightly different than those of its parent
class.
In practice, this class represents manage.py, whereas ManagementUtility
represents django-admin.py.
"""
def __init__(self, argv, project_directory):
super(ProjectManagementUtility, self).__init__(argv)
self.project_directory = project_directory
self.user_commands = True
def setup_environ(settings_mod): def setup_environ(settings_mod):
""" """
Configures the runtime environment. This can also be used by external Configures the runtime environment. This can also be used by external
@ -313,7 +310,6 @@ def setup_environ(settings_mod):
# Set DJANGO_SETTINGS_MODULE appropriately. # Set DJANGO_SETTINGS_MODULE appropriately.
os.environ['DJANGO_SETTINGS_MODULE'] = '%s.%s' % (project_name, settings_name) os.environ['DJANGO_SETTINGS_MODULE'] = '%s.%s' % (project_name, settings_name)
return project_directory
def execute_from_command_line(argv=None): def execute_from_command_line(argv=None):
""" """
@ -327,6 +323,6 @@ def execute_manager(settings_mod, argv=None):
Like execute_from_command_line(), but for use by manage.py, a Like execute_from_command_line(), but for use by manage.py, a
project-specific django-admin.py utility. project-specific django-admin.py utility.
""" """
project_directory = setup_environ(settings_mod) setup_environ(settings_mod)
utility = ProjectManagementUtility(argv, project_directory) utility = ManagementUtility(argv)
utility.execute() utility.execute()

View File

@ -82,9 +82,14 @@ class BaseCommand(object):
# But only do this if we can assume we have a working settings file, # But only do this if we can assume we have a working settings file,
# because django.utils.translation requires settings. # because django.utils.translation requires settings.
if self.can_import_settings: if self.can_import_settings:
from django.utils import translation try:
translation.activate('en-us') from django.utils import translation
translation.activate('en-us')
except ImportError, e:
# If settings should be available, but aren't,
# raise the error and quit.
sys.stderr.write(self.style.ERROR(str('Error: %s\n' % e)))
sys.exit(1)
try: try:
if self.requires_model_validation: if self.requires_model_validation:
self.validate() self.validate()

View File

@ -223,25 +223,25 @@ class DjangoAdminDefaultSettings(AdminScriptTestCase):
self.assertOutput(err, "Could not import settings 'bad_settings'") self.assertOutput(err, "Could not import settings 'bad_settings'")
def test_custom_command(self): def test_custom_command(self):
"default: django-admin can't execute user commands" "default: django-admin can't execute user commands if it isn't provided settings"
args = ['noargs_command'] args = ['noargs_command']
out, err = self.run_django_admin(args) out, err = self.run_django_admin(args)
self.assertNoOutput(out) self.assertNoOutput(out)
self.assertOutput(err, "Unknown command: 'noargs_command'") self.assertOutput(err, "Unknown command: 'noargs_command'")
def test_custom_command_with_settings(self): def test_custom_command_with_settings(self):
"default: django-admin can't execute user commands, even if settings are provided as argument" "default: django-admin can execute user commands if settings are provided as argument"
args = ['noargs_command', '--settings=settings'] args = ['noargs_command', '--settings=settings']
out, err = self.run_django_admin(args) out, err = self.run_django_admin(args)
self.assertNoOutput(out) self.assertNoOutput(err)
self.assertOutput(err, "Unknown command: 'noargs_command'") self.assertOutput(out, "EXECUTE:NoArgsCommand")
def test_custom_command_with_environment(self): def test_custom_command_with_environment(self):
"default: django-admin can't execute user commands, even if settings are provided in environment" "default: django-admin can execute user commands if settings are provided in environment"
args = ['noargs_command'] args = ['noargs_command']
out, err = self.run_django_admin(args,'settings') out, err = self.run_django_admin(args,'settings')
self.assertNoOutput(out) self.assertNoOutput(err)
self.assertOutput(err, "Unknown command: 'noargs_command'") self.assertOutput(out, "EXECUTE:NoArgsCommand")
class DjangoAdminFullPathDefaultSettings(AdminScriptTestCase): class DjangoAdminFullPathDefaultSettings(AdminScriptTestCase):
"""A series of tests for django-admin.py when using a settings.py file that """A series of tests for django-admin.py when using a settings.py file that
@ -261,18 +261,18 @@ class DjangoAdminFullPathDefaultSettings(AdminScriptTestCase):
self.assertOutput(err, 'environment variable DJANGO_SETTINGS_MODULE is undefined') self.assertOutput(err, 'environment variable DJANGO_SETTINGS_MODULE is undefined')
def test_builtin_with_settings(self): def test_builtin_with_settings(self):
"fulldefault: django-admin builtin commands fail if user app isn't on path" "fulldefault: django-admin builtin commands succeed if a settings file is provided"
args = ['sqlall','--settings=settings', 'admin_scripts'] args = ['sqlall','--settings=settings', 'admin_scripts']
out, err = self.run_django_admin(args) out, err = self.run_django_admin(args)
self.assertNoOutput(out) self.assertNoOutput(err)
self.assertOutput(err, 'ImportError: No module named regressiontests') self.assertOutput(out, 'CREATE TABLE')
def test_builtin_with_environment(self): def test_builtin_with_environment(self):
"fulldefault: django-admin builtin commands fail if user app isn't on path" "fulldefault: django-admin builtin commands succeed if the environment contains settings"
args = ['sqlall','admin_scripts'] args = ['sqlall','admin_scripts']
out, err = self.run_django_admin(args,'settings') out, err = self.run_django_admin(args,'settings')
self.assertNoOutput(out) self.assertNoOutput(err)
self.assertOutput(err, 'ImportError: No module named regressiontests') self.assertOutput(out, 'CREATE TABLE')
def test_builtin_with_bad_settings(self): def test_builtin_with_bad_settings(self):
"fulldefault: django-admin builtin commands fail if settings file (from argument) doesn't exist" "fulldefault: django-admin builtin commands fail if settings file (from argument) doesn't exist"
@ -289,25 +289,25 @@ class DjangoAdminFullPathDefaultSettings(AdminScriptTestCase):
self.assertOutput(err, "Could not import settings 'bad_settings'") self.assertOutput(err, "Could not import settings 'bad_settings'")
def test_custom_command(self): def test_custom_command(self):
"fulldefault: django-admin can't execute user commands" "fulldefault: django-admin can't execute user commands unless settings are provided"
args = ['noargs_command'] args = ['noargs_command']
out, err = self.run_django_admin(args) out, err = self.run_django_admin(args)
self.assertNoOutput(out) self.assertNoOutput(out)
self.assertOutput(err, "Unknown command: 'noargs_command'") self.assertOutput(err, "Unknown command: 'noargs_command'")
def test_custom_command_with_settings(self): def test_custom_command_with_settings(self):
"fulldefault: django-admin can't execute user commands, even if settings are provided as argument" "fulldefault: django-admin can execute user commands if settings are provided as argument"
args = ['noargs_command', '--settings=settings'] args = ['noargs_command', '--settings=settings']
out, err = self.run_django_admin(args) out, err = self.run_django_admin(args)
self.assertNoOutput(out) self.assertNoOutput(err)
self.assertOutput(err, "Unknown command: 'noargs_command'") self.assertOutput(out, "EXECUTE:NoArgsCommand")
def test_custom_command_with_environment(self): def test_custom_command_with_environment(self):
"fulldefault: django-admin can't execute user commands, even if settings are provided in environment" "fulldefault: django-admin can execute user commands if settings are provided in environment"
args = ['noargs_command'] args = ['noargs_command']
out, err = self.run_django_admin(args,'settings') out, err = self.run_django_admin(args,'settings')
self.assertNoOutput(out) self.assertNoOutput(err)
self.assertOutput(err, "Unknown command: 'noargs_command'") self.assertOutput(out, "EXECUTE:NoArgsCommand")
class DjangoAdminMinimalSettings(AdminScriptTestCase): class DjangoAdminMinimalSettings(AdminScriptTestCase):
"""A series of tests for django-admin.py when using a settings.py file that """A series of tests for django-admin.py when using a settings.py file that
@ -355,7 +355,7 @@ class DjangoAdminMinimalSettings(AdminScriptTestCase):
self.assertOutput(err, "Could not import settings 'bad_settings'") self.assertOutput(err, "Could not import settings 'bad_settings'")
def test_custom_command(self): def test_custom_command(self):
"minimal: django-admin can't execute user commands" "minimal: django-admin can't execute user commands unless settings are provided"
args = ['noargs_command'] args = ['noargs_command']
out, err = self.run_django_admin(args) out, err = self.run_django_admin(args)
self.assertNoOutput(out) self.assertNoOutput(out)
@ -420,26 +420,26 @@ class DjangoAdminAlternateSettings(AdminScriptTestCase):
self.assertNoOutput(out) self.assertNoOutput(out)
self.assertOutput(err, "Could not import settings 'bad_settings'") self.assertOutput(err, "Could not import settings 'bad_settings'")
def test_custom_command(self): def test_custom_command(self):
"alternate: django-admin can't execute user commands" "alternate: django-admin can't execute user commands unless settings are provided"
args = ['noargs_command'] args = ['noargs_command']
out, err = self.run_django_admin(args) out, err = self.run_django_admin(args)
self.assertNoOutput(out) self.assertNoOutput(out)
self.assertOutput(err, "Unknown command: 'noargs_command'") self.assertOutput(err, "Unknown command: 'noargs_command'")
def test_custom_command_with_settings(self): def test_custom_command_with_settings(self):
"alternate: django-admin can't execute user commands, even if settings are provided as argument" "alternate: django-admin can execute user commands if settings are provided as argument"
args = ['noargs_command', '--settings=alternate_settings'] args = ['noargs_command', '--settings=alternate_settings']
out, err = self.run_django_admin(args) out, err = self.run_django_admin(args)
self.assertNoOutput(out) self.assertNoOutput(err)
self.assertOutput(err, "Unknown command: 'noargs_command'") self.assertOutput(out, "EXECUTE:NoArgsCommand")
def test_custom_command_with_environment(self): def test_custom_command_with_environment(self):
"alternate: django-admin can't execute user commands, even if settings are provided in environment" "alternate: django-admin can execute user commands if settings are provided in environment"
args = ['noargs_command'] args = ['noargs_command']
out, err = self.run_django_admin(args,'alternate_settings') out, err = self.run_django_admin(args,'alternate_settings')
self.assertNoOutput(out) self.assertNoOutput(err)
self.assertOutput(err, "Unknown command: 'noargs_command'") self.assertOutput(out, "EXECUTE:NoArgsCommand")
class DjangoAdminMultipleSettings(AdminScriptTestCase): class DjangoAdminMultipleSettings(AdminScriptTestCase):
@ -490,8 +490,8 @@ class DjangoAdminMultipleSettings(AdminScriptTestCase):
self.assertNoOutput(out) self.assertNoOutput(out)
self.assertOutput(err, "Could not import settings 'bad_settings'") self.assertOutput(err, "Could not import settings 'bad_settings'")
def test_custom_command(self): def test_custom_command(self):
"alternate: django-admin can't execute user commands" "alternate: django-admin can't execute user commands unless settings are provided"
args = ['noargs_command'] args = ['noargs_command']
out, err = self.run_django_admin(args) out, err = self.run_django_admin(args)
self.assertNoOutput(out) self.assertNoOutput(out)
@ -501,15 +501,15 @@ class DjangoAdminMultipleSettings(AdminScriptTestCase):
"alternate: django-admin can't execute user commands, even if settings are provided as argument" "alternate: django-admin can't execute user commands, even if settings are provided as argument"
args = ['noargs_command', '--settings=alternate_settings'] args = ['noargs_command', '--settings=alternate_settings']
out, err = self.run_django_admin(args) out, err = self.run_django_admin(args)
self.assertNoOutput(out) self.assertNoOutput(err)
self.assertOutput(err, "Unknown command: 'noargs_command'") self.assertOutput(out, "EXECUTE:NoArgsCommand")
def test_custom_command_with_environment(self): def test_custom_command_with_environment(self):
"alternate: django-admin can't execute user commands, even if settings are provided in environment" "alternate: django-admin can't execute user commands, even if settings are provided in environment"
args = ['noargs_command'] args = ['noargs_command']
out, err = self.run_django_admin(args,'alternate_settings') out, err = self.run_django_admin(args,'alternate_settings')
self.assertNoOutput(out) self.assertNoOutput(err)
self.assertOutput(err, "Unknown command: 'noargs_command'") self.assertOutput(out, "EXECUTE:NoArgsCommand")
########################################################################## ##########################################################################
# MANAGE.PY TESTS # MANAGE.PY TESTS