diff --git a/django/core/management/commands/shell.py b/django/core/management/commands/shell.py index 7d2ce62070..dfc7d78691 100644 --- a/django/core/management/commands/shell.py +++ b/django/core/management/commands/shell.py @@ -18,6 +18,8 @@ class Command(BaseCommand): help='When using plain Python, ignore the PYTHONSTARTUP environment variable and ~/.pythonrc.py script.') parser.add_argument('-i', '--interface', choices=self.shells, dest='interface', help='Specify an interactive interpreter interface. Available options: "ipython", "bpython", and "python"') + parser.add_argument('-c', '--command', dest='command', + help='Instead of opening an interactive shell, run a command as Django and exit.') def _ipython_pre_011(self): """Start IPython pre-0.11""" @@ -93,6 +95,11 @@ class Command(BaseCommand): ) options['interface'] = 'python' + # Execute the command and exit. + if options['command']: + exec(options['command']) + return + available_shells = [options['interface']] if options['interface'] else self.shells for shell in available_shells: diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt index 24ea5906ae..870f5dfc5c 100644 --- a/docs/ref/django-admin.txt +++ b/docs/ref/django-admin.txt @@ -970,6 +970,15 @@ behavior you can use the ``--no-startup`` option. e.g.:: django-admin shell --interface python --no-startup +.. django-admin-option:: --command, -c + +.. versionadded:: 1.10 + +The ``--command`` option lets you pass a command as a string to execute it as +Django, like so:: + + django-admin shell --command="import django; print(django.__version__)" + showmigrations [ []] ------------------------------------------ diff --git a/docs/releases/1.10.txt b/docs/releases/1.10.txt index 94565ccec7..0eec66faee 100644 --- a/docs/releases/1.10.txt +++ b/docs/releases/1.10.txt @@ -224,6 +224,9 @@ Management Commands * The :djadmin:`shell` ``--interface`` option now accepts ``python`` to force use of the "plain" Python interpreter. +* The new :djadminopt:`shell --command <--command>` option lets you run a + command as Django and exit, instead of opening the interactive shell. + Migrations ^^^^^^^^^^ diff --git a/tests/shell/__init__.py b/tests/shell/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/shell/tests.py b/tests/shell/tests.py new file mode 100644 index 0000000000..7285c968a2 --- /dev/null +++ b/tests/shell/tests.py @@ -0,0 +1,19 @@ +from django import __version__ +from django.core.management import call_command +from django.test import SimpleTestCase +from django.test.utils import patch_logger + + +class ShellCommandTestCase(SimpleTestCase): + + def test_command_option(self): + with patch_logger('test', 'info') as logger: + call_command( + 'shell', + command=( + 'import django; from logging import getLogger; ' + 'getLogger("test").info(django.__version__)' + ), + ) + self.assertEqual(len(logger), 1) + self.assertEqual(logger[0], __version__)