Skip to content
Browse files

Major refactoring of -- it's now a package rat…

…her than a 1730-line single module. All django-admin/ commands are now stored in separate modules. This is backwards-incompatible for people who used functions directly

git-svn-id: bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
adrianholovaty committed Aug 16, 2007
1 parent 7f06e44 commit 01adbb55e6698b512ff202bc5fc81f9565e4003b
Showing with 1,972 additions and 1,771 deletions.
  1. +0 −1,730 django/core/
  2. +180 −0 django/core/management/
  3. +131 −0 django/core/management/
  4. +28 −0 django/core/management/
  5. 0 django/core/management/commands/
  6. +33 −0 django/core/management/commands/
  7. +40 −0 django/core/management/commands/
  8. +10 −0 django/core/management/commands/
  9. +32 −0 django/core/management/commands/
  10. +33 −0 django/core/management/commands/
  11. +64 −0 django/core/management/commands/
  12. +120 −0 django/core/management/commands/
  13. +123 −0 django/core/management/commands/
  14. +47 −0 django/core/management/commands/
  15. +16 −0 django/core/management/commands/
  16. +65 −0 django/core/management/commands/
  17. +42 −0 django/core/management/commands/
  18. +10 −0 django/core/management/commands/
  19. +10 −0 django/core/management/commands/
  20. +10 −0 django/core/management/commands/
  21. +10 −0 django/core/management/commands/
  22. +10 −0 django/core/management/commands/
  23. +10 −0 django/core/management/commands/
  24. +7 −0 django/core/management/commands/
  25. +10 −0 django/core/management/commands/
  26. +9 −0 django/core/management/commands/
  27. +33 −0 django/core/management/commands/
  28. +39 −0 django/core/management/commands/
  29. +129 −0 django/core/management/commands/
  30. +27 −0 django/core/management/commands/
  31. +9 −0 django/core/management/commands/
  32. +420 −0 django/core/management/
  33. +221 −0 django/core/management/
  34. +6 −3 django/test/
  35. +21 −21 django/test/
  36. +9 −9 tests/modeltests/fixtures/
  37. +2 −2 tests/regressiontests/fixtures_regress/
  38. +4 −4 tests/regressiontests/serializers_regress/
  39. +2 −2 tests/

This file was deleted.

Oops, something went wrong.
@@ -0,0 +1,180 @@
import django
from optparse import OptionParser
import os
import sys
import textwrap

# For backwards compatibility: get_version() used to be in this module.
get_version = django.get_version

def load_command_class(name):
Given a command name, returns the Command class instance. Raises
ImportError if it doesn't exist.
# Let the ImportError propogate.
return getattr(__import__('' % name, {}, {}, ['Command']), 'Command')()

def call_command(name, *args, **options):
Calls the given command, with the given options and args/kwargs.
This is the primary API you should use for calling specific commands.
Some examples:
call_command('shell', plain=True)
call_command('sqlall', 'myapp')
klass = load_command_class(name)
return klass.execute(*args, **options)

class ManagementUtility(object):
Encapsulates the logic of the and utilities.
A ManagementUtility has a number of commands, which can be manipulated
by editing the self.commands dictionary.
def __init__(self):
self.commands = self.default_commands()

def default_commands(self):
Returns a dictionary of instances of all available Command classes.
This works by looking for and loading all Python modules in the package.
The dictionary is in the format {name: command_instance}.
command_dir = os.path.join(__path__[0], 'commands')
names = [f[:-3] for f in os.listdir(command_dir) if not f.startswith('_') and f.endswith('.py')]
return dict([(name, load_command_class(name)) for name in names])

def usage(self):
Returns a usage string, for use with optparse.
The string doesn't include the options (e.g., "--verbose"), because
optparse puts those in automatically.
usage = ["%prog command [options]\nactions:"]
commands = self.commands.items()
for name, cmd in commands:
usage.append(' %s %s' % (name, cmd.args))
usage.extend(textwrap.wrap(, initial_indent=' ', subsequent_indent=' '))
return '\n'.join(usage[:-1]) # Cut off the last list element, an empty space.

def execute(self, argv=None):
Parses the given argv from the command line, determines which command
to run and runs the command.
if argv is None:
argv = sys.argv

# Create the parser object and parse the command-line args.
# TODO: Ideally each Command class would register its own options for
# add_option(), but we'd need to figure out how to allow for multiple
# Commands using the same options. The optparse library gets in the way
# by checking for conflicts:
parser = OptionParser(usage=self.usage(), version=get_version())
help='The Python path to a settings module, e.g. "myproject.settings.main". If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be used.')
help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".')
parser.add_option('--plain', action='store_true', dest='plain',
help='When using "shell": Tells Django to use plain Python, not IPython.')
parser.add_option('--noinput', action='store_false', dest='interactive', default=True,
help='Tells Django to NOT prompt the user for input of any kind.')
parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True,
help='When using "runserver": Tells Django to NOT use the auto-reloader.')
parser.add_option('--format', default='json', dest='format',
help='Specifies the output serialization format for fixtures')
parser.add_option('--indent', default=None, dest='indent',
type='int', help='Specifies the indent level to use when pretty-printing output')
parser.add_option('--verbosity', action='store', dest='verbosity', default='1',
type='choice', choices=['0', '1', '2'],
help='Verbosity level; 0=minimal output, 1=normal output, 2=all output')
parser.add_option('--adminmedia', dest='admin_media_path', default='',
help='When using "runserver": Specifies the directory from which to serve admin media.')
options, args = parser.parse_args(argv[1:])

# If the 'settings' or 'pythonpath' options were submitted, activate those.
if options.settings:
os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
if options.pythonpath:
sys.path.insert(0, options.pythonpath)

# Run the appropriate command.
command_name = args[0]
except IndexError:
sys.stderr.write("Type '%s --help' for usage.\n" % os.path.basename(argv[0]))
command = self.commands[command_name]
except KeyError:
sys.stderr.write("Unknown command: %r\nType '%s --help' for usage.\n" % (command_name, os.path.basename(argv[0])))
command.execute(*args[1:], **options.__dict__)

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
In practice, this class represents, whereas ManagementUtility
def __init__(self, project_directory):
super(ProjectManagementUtility, self).__init__()

# Remove the "startproject" command from self.commands, because
# that's a command, not a command.
del self.commands['startproject']

# Override the startapp command so that it always uses the
# project_directory, not the current working directory (which is default).
from import ProjectCommand
self.commands['startapp'] = ProjectCommand(project_directory)

def setup_environ(settings_mod):
Configure the runtime environment. This can also be used by external
scripts wanting to set up a similar environment to
# Add this project to sys.path so that it's importable in the conventional
# way. For example, if this file ( lives in a directory
# "myproject", this code would add "/path/to/myproject" to sys.path.
project_directory, settings_filename = os.path.split(settings_mod.__file__)
project_name = os.path.basename(project_directory)
settings_name = os.path.splitext(settings_filename)[0]
sys.path.append(os.path.join(project_directory, '..'))
project_module = __import__(project_name, {}, {}, [''])

# Set DJANGO_SETTINGS_MODULE appropriately.
os.environ['DJANGO_SETTINGS_MODULE'] = '%s.%s' % (project_name, settings_name)
return project_directory

def execute_from_command_line(argv=None):
A simple method that runs a ManagementUtility.
utility = ManagementUtility()

def execute_manager(settings_mod, argv=None):
Like execute_from_command_line(), but for use by, a
project-specific utility.
project_directory = setup_environ(settings_mod)
utility = ProjectManagementUtility(project_directory)
@@ -0,0 +1,131 @@
from django.core.exceptions import ImproperlyConfigured
from import color_style
import sys

class CommandError(Exception):

class BaseCommand(object):
# Metadata about this command.
help = ''
args = ''

# Configuration shortcuts that alter various logic.
can_import_settings = True
requires_model_validation = True
output_transaction = False # Whether to wrap the output in a "BEGIN; COMMIT;"

def __init__(self): = color_style()

def execute(self, *args, **options):
# Switch to English, because creates database content
# like permissions, and those shouldn't contain any translations.
# But only do this if we can assume we have a working settings file,
# because django.utils.translation requires settings.
if self.can_import_settings:
from django.utils import translation

if self.requires_model_validation:
output = self.handle(*args, **options)
if output:
if self.output_transaction:
# This needs to be imported here, because it relies on settings.
from django.db import backend
if backend.get_start_transaction_sql():
print output
if self.output_transaction:
except CommandError, e:
sys.stderr.write('Error: %s\n' % e)))

def validate(self, app=None):
Validates the given app, raising CommandError for any errors.
If app is None, then this will validate all installed apps.
from import get_validation_errors
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
s = StringIO()
num_errors = get_validation_errors(s, app)
if num_errors:
error_text =
raise CommandError("One or more models did not validate:\n%s" % error_text)

def handle(self, *args, **options):
raise NotImplementedError()

class AppCommand(BaseCommand):
args = '[appname ...]'

def handle(self, *app_labels, **options):
from django.db import models
if not app_labels:
raise CommandError('Enter at least one appname.')
app_list = [models.get_app(app_label) for app_label in app_labels]
except (ImproperlyConfigured, ImportError), e:
raise CommandError("%s. Are you sure your INSTALLED_APPS setting is correct?" % e)
output = []
for app in app_list:
app_output = self.handle_app(app, **options)
if app_output:
return '\n'.join(output)

def handle_app(self, app, **options):
raise NotImplementedError()

class CopyFilesCommand(BaseCommand):
requires_model_validation = False

def copy_helper(self, app_or_project, name, directory, other_name=''):
import django
import os
import re
import shutil
other = {'project': 'app', 'app': 'project'}[app_or_project]
if not'^\w+$', name): # If it's not a valid directory name.
raise CommandError("%r is not a valid %s name. Please use only numbers, letters and underscores." % (name, app_or_project))
top_dir = os.path.join(directory, name)
except OSError, e:
raise CommandError(e)

# Determine where the app or project templates are. Use
# django.__path__[0] because we don't know into which directory
# django has been installed.
template_dir = os.path.join(django.__path__[0], 'conf', '%s_template' % app_or_project)

for d, subdirs, files in os.walk(template_dir):
relative_dir = d[len(template_dir)+1:].replace('%s_name' % app_or_project, name)
if relative_dir:
os.mkdir(os.path.join(top_dir, relative_dir))
for i, subdir in enumerate(subdirs):
if subdir.startswith('.'):
del subdirs[i]
for f in files:
if f.endswith('.pyc'):
path_old = os.path.join(d, f)
path_new = os.path.join(top_dir, relative_dir, f.replace('%s_name' % app_or_project, name))
fp_old = open(path_old, 'r')
fp_new = open(path_new, 'w')
fp_new.write('{{ %s_name }}' % app_or_project, name).replace('{{ %s_name }}' % other, other_name))
shutil.copymode(path_old, path_new)
except OSError:
sys.stderr.write("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new))
@@ -0,0 +1,28 @@
Sets up the terminal color scheme.

from django.utils import termcolors
import sys

def color_style():
"Returns a Style object with the Django color scheme."
if sys.platform == 'win32' or sys.platform == 'Pocket PC' or not sys.stdout.isatty():
return no_style()
class dummy: pass
style = dummy()
style.ERROR = termcolors.make_style(fg='red', opts=('bold',))
style.ERROR_OUTPUT = termcolors.make_style(fg='red', opts=('bold',))
style.NOTICE = termcolors.make_style(fg='red')
style.SQL_FIELD = termcolors.make_style(fg='green', opts=('bold',))
style.SQL_COLTYPE = termcolors.make_style(fg='green')
style.SQL_KEYWORD = termcolors.make_style(fg='yellow')
style.SQL_TABLE = termcolors.make_style(opts=('bold',))
return style

def no_style():
"Returns a Style object that has no colors."
class dummy:
def __getattr__(self, attr):
return lambda x: x
return dummy()
No changes.
@@ -0,0 +1,33 @@
from import AppCommand
from django.utils.text import capfirst

MODULE_TEMPLATE = ''' {%% if perms.%(app)s.%(addperm)s or perms.%(app)s.%(changeperm)s %%}
<th>{%% if perms.%(app)s.%(changeperm)s %%}<a href="%(app)s/%(mod)s/">{%% endif %%}%(name)s{%% if perms.%(app)s.%(changeperm)s %%}</a>{%% endif %%}</th>
<td class="x50">{%% if perms.%(app)s.%(addperm)s %%}<a href="%(app)s/%(mod)s/add/" class="addlink">{%% endif %%}Add{%% if perms.%(app)s.%(addperm)s %%}</a>{%% endif %%}</td>
<td class="x75">{%% if perms.%(app)s.%(changeperm)s %%}<a href="%(app)s/%(mod)s/" class="changelink">{%% endif %%}Change{%% if perms.%(app)s.%(changeperm)s %%}</a>{%% endif %%}</td>
{%% endif %%}'''

class Command(AppCommand):
help = 'Prints the admin-index template snippet for the given app name(s).'

def handle_app(self, app, **options):
from django.db.models import get_models
output = []
app_models = get_models(app)
app_label = app_models[0]._meta.app_label
output.append('{%% if perms.%s %%}' % app_label)
output.append('<div class="module"><h2>%s</h2><table>' % app_label.title())
for model in app_models:
if model._meta.admin:
output.append(MODULE_TEMPLATE % {
'app': app_label,
'mod': model._meta.module_name,
'name': capfirst(model._meta.verbose_name_plural),
'addperm': model._meta.get_add_permission(),
'changeperm': model._meta.get_change_permission(),
output.append('{% endif %}')
return '\n'.join(output)
Oops, something went wrong.

0 comments on commit 01adbb5

Please sign in to comment.
You can’t perform that action at this time.