12
18
from sets import Set as set # For Python 2.3
14
20
class CommandError(Exception):
22
Exception class indicating a problem while executing a management
25
If this exception is raised during the execution of a management
26
command, it will be caught and turned into a nicely-printed error
27
message to the appropriate output stream (i.e., stderr); as a
28
result, raising this exception (with a sensible description of the
29
error) is the preferred way to indicate that something has gone
30
wrong in the execution of a command.
17
35
def handle_default_options(options):
19
Include any default options that all commands should accept
20
here so that ManagementUtility can handle them before searching
37
Include any default options that all commands should accept here
38
so that ManagementUtility can handle them before searching for
23
42
if options.settings:
24
43
os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
26
45
sys.path.insert(0, options.pythonpath)
28
47
class BaseCommand(object):
49
The base class from which all management commands ultimately
52
Use this class if you want access to all of the mechanisms which
53
parse the command-line arguments and work out what code to call in
54
response; if you don't need to change any of that behavior,
55
consider using one of the subclasses defined in this file.
57
If you are interested in overriding/customizing various aspects of
58
the command-parsing and -execution behavior, the normal flow works
61
1. ``django-admin.py`` or ``manage.py`` loads the command class
62
and calls its ``run_from_argv()`` method.
64
2. The ``run_from_argv()`` method calls ``create_parser()`` to get
65
an ``OptionParser`` for the arguments, parses them, performs
66
any environment changes requested by options like
67
``pythonpath``, and then calls the ``execute()`` method,
68
passing the parsed arguments.
70
3. The ``execute()`` method attempts to carry out the command by
71
calling the ``handle()`` method with the parsed arguments; any
72
output produced by ``handle()`` will be printed to standard
73
output and, if the command is intended to produce a block of
74
SQL statements, will be wrapped in ``BEGIN`` and ``COMMIT``.
76
4. If ``handle()`` raised a ``ComandError``, ``execute()`` will
77
instead print an error message to ``stderr``.
79
Thus, the ``handle()`` method is typically the starting point for
80
subclasses; many built-in commands and command types either place
81
all of their logic in ``handle()``, or perform some additional
82
parsing work in ``handle()`` and then delegate from it to more
83
specialized methods as needed.
85
Several attributes affect behavior at various steps along the way:
88
A string listing the arguments accepted by the command,
89
suitable for use in help messages; e.g., a command which takes
90
a list of application names might set this to '<appname
93
``can_import_settings``
94
A boolean indicating whether the command needs to be able to
95
import Django settings; if ``True``, ``execute()`` will verify
96
that this is possible before proceeding. Default value is
100
A short description of the command, which will be printed in
104
This is the list of ``optparse`` options which will be fed
105
into the command's ``OptionParser`` for parsing arguments.
107
``output_transaction``
108
A boolean indicating whether the command outputs SQL
109
statements; if ``True``, the output will automatically be
110
wrapped with ``BEGIN;`` and ``COMMIT;``. Default value is
113
``requires_model_validation``
114
A boolean; if ``True``, validation of installed models will be
115
performed prior to executing the command. Default value is
116
``True``. To validate an individual application's models
117
rather than all applications' models, call
118
``self.validate(app)`` from ``handle()``, where ``app`` is the
119
application's Python module.
29
122
# Metadata about this command.
31
124
make_option('--settings',
49
142
def get_version(self):
51
Returns the Django version, which should be correct for all built-in
52
Django commands. User-supplied commands should override this method.
144
Return the Django version, which should be correct for all
145
built-in Django commands. User-supplied commands should
146
override this method.
54
149
return django.get_version()
56
151
def usage(self, subcommand):
153
Return a brief description of how to use this command, by
154
default from the attribute ``self.help``.
57
157
usage = '%%prog %s [options] %s' % (subcommand, self.args)
59
159
return '%s\n\n%s' % (usage, self.help)
63
163
def create_parser(self, prog_name, subcommand):
165
Create and return the ``OptionParser`` which will be used to
166
parse the arguments to this command.
64
169
return OptionParser(prog=prog_name,
65
170
usage=self.usage(subcommand),
66
171
version=self.get_version(),
67
172
option_list=self.option_list)
69
174
def print_help(self, prog_name, subcommand):
176
Print the help message for this command, derived from
70
180
parser = self.create_parser(prog_name, subcommand)
71
181
parser.print_help()
73
183
def run_from_argv(self, argv):
185
Set up any environment changes requested (e.g., Python path
186
and Django settings), then run this command.
74
189
parser = self.create_parser(argv[0], argv[1])
75
190
options, args = parser.parse_args(argv[2:])
76
191
handle_default_options(options)
77
192
self.execute(*args, **options.__dict__)
79
194
def execute(self, *args, **options):
196
Try to execute this command, performing model validation if
197
needed (as controlled by the attribute
198
``self.requires_model_validation``). If the command raises a
199
``CommandError``, intercept it and print it sensibly to
80
203
# Switch to English, because django-admin.py creates database content
81
204
# like permissions, and those shouldn't contain any translations.
82
205
# But only do this if we can assume we have a working settings file,
128
252
print "%s error%s found" % (num_errors, num_errors != 1 and 's' or '')
130
254
def handle(self, *args, **options):
256
The actual logic of the command. Subclasses must implement
131
260
raise NotImplementedError()
133
262
class AppCommand(BaseCommand):
264
A management command which takes one or more installed application
265
names as arguments, and does something with each of them.
267
Rather than implementing ``handle()``, subclasses must implement
268
``handle_app()``, which will be called once for each application.
134
271
args = '<appname appname ...>'
136
273
def handle(self, *app_labels, **options):
149
286
return '\n'.join(output)
151
288
def handle_app(self, app, **options):
290
Perform the command's actions for ``app``, which will be the
291
Python module corresponding to an application name given on
152
295
raise NotImplementedError()
154
297
class LabelCommand(BaseCommand):
299
A management command which takes one or more arbitrary arguments
300
(labels) on the command line, and does something with each of
303
Rather than implementing ``handle()``, subclasses must implement
304
``handle_label()``, which will be called once for each label.
306
If the arguments should be names of installed applications, use
307
``AppCommand`` instead.
155
310
args = '<label label ...>'
167
322
return '\n'.join(output)
169
324
def handle_label(self, label, **options):
326
Perform the command's actions for ``label``, which will be the
327
string as given on the command line.
170
330
raise NotImplementedError()
172
332
class NoArgsCommand(BaseCommand):
334
A command which takes no arguments on the command line.
336
Rather than implementing ``handle()``, subclasses must implement
337
``handle_noargs()``; ``handle()`` itself is overridden to ensure
338
no arguments are passed to the command.
340
Attempting to pass arguments will raise ``CommandError``.
175
345
def handle(self, *args, **options):
178
348
return self.handle_noargs(**options)
180
350
def handle_noargs(self, **options):
352
Perform this command's actions.
181
355
raise NotImplementedError()
183
357
def copy_helper(style, app_or_project, name, directory, other_name=''):
185
359
Copies either a Django application layout template or a Django project
186
360
layout template into the specified directory.
188
363
# style -- A color style object (see django.core.management.color).
189
364
# app_or_project -- The string 'app' or 'project'.
196
371
other = {'project': 'app', 'app': 'project'}[app_or_project]
197
if not re.search(r'^\w+$', name): # If it's not a valid directory name.
198
raise CommandError("%r is not a valid %s name. Please use only numbers, letters and underscores." % (name, app_or_project))
372
if not re.search(r'^[_a-zA-Z]\w*$', name): # If it's not a valid directory name.
373
# Provide a smart error message, depending on the error.
374
if not re.search(r'^[_a-zA-Z]', name):
375
message = 'make sure the name begins with a letter or underscore'
377
message = 'use only numbers, letters and underscores'
378
raise CommandError("%r is not a valid %s name. Please %s." % (name, app_or_project, message))
199
379
top_dir = os.path.join(directory, name)
201
381
os.mkdir(top_dir)