PageRenderTime 96ms CodeModel.GetById 91ms app.highlight 2ms RepoModel.GetById 1ms app.codeStats 0ms

/docs/howto/custom-management-commands.txt

https://code.google.com/p/mango-py/
Plain Text | 307 lines | 218 code | 89 blank | 0 comment | 0 complexity | 65db32dd77e2dff468d0dceb2eaa81e2 MD5 | raw file
  1====================================
  2Writing custom django-admin commands
  3====================================
  4
  5Applications can register their own actions with ``manage.py``. For example,
  6you might want to add a ``manage.py`` action for a Django app that you're
  7distributing. In this document, we will be building a custom ``closepoll``
  8command for the ``polls`` application from the
  9:doc:`tutorial</intro/tutorial01>`.
 10
 11To do this, just add a ``management/commands`` directory to the application.
 12Each Python module in that directory will be auto-discovered and registered as
 13a command that can be executed as an action when you run ``manage.py``::
 14
 15    polls/
 16        __init__.py
 17        models.py
 18        management/
 19            __init__.py
 20            commands/
 21                __init__.py
 22                closepoll.py
 23        tests.py
 24        views.py
 25
 26In this example, the ``closepoll`` command will be made available to any project
 27that includes the ``polls`` application in :setting:`INSTALLED_APPS`.
 28
 29The ``closepoll.py`` module has only one requirement -- it must define a class
 30``Command`` that extends :class:`BaseCommand` or one of its
 31:ref:`subclasses<ref-basecommand-subclasses>`.
 32
 33.. admonition:: Standalone scripts
 34
 35  Custom management commands are especially useful for running standalone
 36  scripts or for scripts that are periodically executed from the UNIX crontab
 37  or from Windows scheduled tasks control panel.
 38
 39To implement the command, edit ``polls/management/commands/closepoll.py`` to
 40look like this:
 41
 42.. code-block:: python
 43
 44    from django.core.management.base import BaseCommand, CommandError
 45    from example.polls.models import Poll
 46
 47    class Command(BaseCommand):
 48        args = '<poll_id poll_id ...>'
 49        help = 'Closes the specified poll for voting'
 50
 51        def handle(self, *args, **options):
 52            for poll_id in args:
 53                try:
 54                    poll = Poll.objects.get(pk=int(poll_id))
 55                except Poll.DoesNotExist:
 56                    raise CommandError('Poll "%s" does not exist' % poll_id)
 57
 58                poll.opened = False
 59                poll.save()
 60
 61                self.stdout.write('Successfully closed poll "%s"\n' % poll_id)
 62
 63.. note::
 64    When you are using management commands and wish to provide console
 65    output, you should write to ``self.stdout`` and ``self.stderr``,
 66    instead of printing to ``stdout`` and ``stderr`` directly. By
 67    using these proxies, it becomes much easier to test your custom
 68    command.
 69
 70The new custom command can be called using ``python manage.py closepoll
 71<poll_id>``.
 72
 73The ``handle()`` method takes zero or more ``poll_ids`` and sets ``poll.opened``
 74to ``False`` for each one. If the user referenced any nonexistent polls, a
 75:class:`CommandError` is raised. The ``poll.opened`` attribute does not exist
 76in the :doc:`tutorial</intro/tutorial01>` and was added to
 77``polls.models.Poll`` for this example.
 78
 79The same ``closepoll`` could be easily modified to delete a given poll instead
 80of closing it by accepting additional command line options. These custom options
 81must be added to :attr:`~BaseCommand.option_list` like this:
 82
 83.. code-block:: python
 84
 85    from optparse import make_option
 86
 87    class Command(BaseCommand):
 88        option_list = BaseCommand.option_list + (
 89            make_option('--delete',
 90                action='store_true',
 91                dest='delete',
 92                default=False,
 93                help='Delete poll instead of closing it'),
 94            )
 95        # ...
 96
 97In addition to being able to add custom command line options, all
 98:doc:`management commands</ref/django-admin>` can accept some
 99default options such as :djadminopt:`--verbosity` and :djadminopt:`--traceback`.
100
101.. admonition:: Management commands and locales
102
103    The :meth:`BaseCommand.execute` method sets the hardcoded ``en-us`` locale
104    because the commands shipped with Django perform several tasks
105    (for example, user-facing content rendering and database population) that
106    require a system-neutral string language (for which we use ``en-us``).
107
108    If your custom management command uses another locale, you should manually
109    activate and deactivate it in your :meth:`~BaseCommand.handle` or
110    :meth:`~NoArgsCommand.handle_noargs` method using the functions provided by
111    the I18N support code:
112
113    .. code-block:: python
114
115        from django.core.management.base import BaseCommand, CommandError
116        from django.utils import translation
117
118        class Command(BaseCommand):
119            ...
120            self.can_import_settings = True
121
122            def handle(self, *args, **options):
123
124                # Activate a fixed locale, e.g. Russian
125                translation.activate('ru')
126
127                # Or you can activate the LANGUAGE_CODE
128                # chosen in the settings:
129                #
130                #from django.conf import settings
131                #translation.activate(settings.LANGUAGE_CODE)
132
133                # Your command logic here
134                # ...
135
136                translation.deactivate()
137
138    Take into account though, that system management commands typically have to
139    be very careful about running in non-uniform locales, so:
140
141    * Make sure the :setting:`USE_I18N` setting is always ``True`` when running
142      the command (this is one good example of the potential problems stemming
143      from a dynamic runtime environment that Django commands avoid offhand by
144      always using a fixed locale).
145
146    * Review the code of your command and the code it calls for behavioral
147      differences when locales are changed and evaluate its impact on
148      predictable behavior of your command.
149
150Command objects
151===============
152
153.. class:: BaseCommand
154
155The base class from which all management commands ultimately derive.
156
157Use this class if you want access to all of the mechanisms which
158parse the command-line arguments and work out what code to call in
159response; if you don't need to change any of that behavior,
160consider using one of its :ref:`subclasses<ref-basecommand-subclasses>`.
161
162Subclassing the :class:`BaseCommand` class requires that you implement the
163:meth:`~BaseCommand.handle` method.
164
165Attributes
166----------
167
168All attributes can be set in your derived class and can be used in
169:class:`BaseCommand`'s :ref:`subclasses<ref-basecommand-subclasses>`.
170
171.. attribute:: BaseCommand.args
172
173  A string listing the arguments accepted by the command,
174  suitable for use in help messages; e.g., a command which takes
175  a list of application names might set this to '<appname
176  appname ...>'.
177
178.. attribute:: BaseCommand.can_import_settings
179
180  A boolean indicating whether the command needs to be able to
181  import Django settings; if ``True``, ``execute()`` will verify
182  that this is possible before proceeding. Default value is
183  ``True``.
184
185.. attribute:: BaseCommand.help
186
187  A short description of the command, which will be printed in the
188  help message when the user runs the command
189  ``python manage.py help <command>``.
190
191.. attribute:: BaseCommand.option_list
192
193  This is the list of ``optparse`` options which will be fed
194  into the command's ``OptionParser`` for parsing arguments.
195
196.. attribute:: BaseCommand.output_transaction
197
198  A boolean indicating whether the command outputs SQL
199  statements; if ``True``, the output will automatically be
200  wrapped with ``BEGIN;`` and ``COMMIT;``. Default value is
201  ``False``.
202
203.. attribute:: BaseCommand.requires_model_validation
204
205  A boolean; if ``True``, validation of installed models will be
206  performed prior to executing the command. Default value is
207  ``True``. To validate an individual application's models
208  rather than all applications' models, call
209  :meth:`~BaseCommand.validate` from :meth:`~BaseCommand.handle`.
210
211Methods
212-------
213
214:class:`BaseCommand` has a few methods that can be overridden but only
215the :meth:`~BaseCommand.handle` method must be implemented.
216
217.. admonition:: Implementing a constructor in a subclass
218
219  If you implement ``__init__`` in your subclass of :class:`BaseCommand`,
220  you must call :class:`BaseCommand`'s ``__init__``.
221
222  .. code-block:: python
223
224    class Command(BaseCommand):
225        def __init__(self, *args, **kwargs):
226            super(Command, self).__init__(*args, **kwargs)
227            # ...
228
229.. method:: BaseCommand.get_version()
230
231    Return the Django version, which should be correct for all
232    built-in Django commands. User-supplied commands can
233    override this method to return their own version.
234
235.. method:: BaseCommand.execute(*args, **options)
236
237    Try to execute this command, performing model validation if
238    needed (as controlled by the attribute
239    :attr:`requires_model_validation`). If the command raises a
240    :class:`CommandError`, intercept it and print it sensibly to
241    stderr.
242
243.. method:: BaseCommand.handle(*args, **options)
244
245    The actual logic of the command. Subclasses must implement this method.
246
247.. _ref-basecommand-subclasses:
248
249BaseCommand subclasses
250----------------------
251
252.. class:: AppCommand
253
254A management command which takes one or more installed application
255names as arguments, and does something with each of them.
256
257Rather than implementing :meth:`~BaseCommand.handle`, subclasses must implement
258:meth:`~AppCommand.handle_app`, which will be called once for each application.
259
260.. method:: AppCommand.handle_app(app, **options)
261
262    Perform the command's actions for ``app``, which will be the
263    Python module corresponding to an application name given on
264    the command line.
265
266.. class:: LabelCommand
267
268A management command which takes one or more arbitrary arguments
269(labels) on the command line, and does something with each of
270them.
271
272Rather than implementing :meth:`~BaseCommand.handle`, subclasses must implement
273:meth:`~LabelCommand.handle_label`, which will be called once for each label.
274
275.. method:: LabelCommand.handle_label(label, **options)
276
277    Perform the command's actions for ``label``, which will be the
278    string as given on the command line.
279
280.. class:: NoArgsCommand
281
282A command which takes no arguments on the command line.
283
284Rather than implementing :meth:`~BaseCommand.handle`, subclasses must implement
285:meth:`~NoArgsCommand.handle_noargs`; :meth:`~BaseCommand.handle` itself is
286overridden to ensure no arguments are passed to the command.
287
288.. method:: NoArgsCommand.handle_noargs(**options)
289
290    Perform this command's actions
291
292.. _ref-command-exceptions:
293
294Command exceptions
295------------------
296
297.. class:: CommandError
298
299Exception class indicating a problem while executing a management
300command.
301
302If this exception is raised during the execution of a management
303command, it will be caught and turned into a nicely-printed error
304message to the appropriate output stream (i.e., stderr); as a
305result, raising this exception (with a sensible description of the
306error) is the preferred way to indicate that something has gone
307wrong in the execution of a command.