Loading django/core/management/__init__.py +5 −1 Original line number Diff line number Diff line Loading @@ -102,8 +102,12 @@ def call_command(name, *args, **options): # Simulate argument parsing to get the option defaults (see #10080 for details). parser = command.create_parser('', name) if command.use_argparse: # Use the `dest` option name from the parser option opt_mapping = dict((sorted(s_opt.option_strings)[0].lstrip('-').replace('-', '_'), s_opt.dest) for s_opt in parser._actions if s_opt.option_strings) arg_options = dict((opt_mapping.get(key, key), value) for key, value in options.items()) defaults = parser.parse_args(args=args) defaults = dict(defaults._get_kwargs(), **options) defaults = dict(defaults._get_kwargs(), **arg_options) else: # Legacy optparse method defaults, _ = parser.parse_args(args=[]) Loading docs/ref/django-admin.txt +18 −1 Original line number Diff line number Diff line Loading @@ -1824,10 +1824,27 @@ Examples:: management.call_command('loaddata', 'test_data', verbosity=0) Note that command options that take no arguments are passed as keywords with ``True`` or ``False``:: with ``True`` or ``False``, as you can see with the ``interactive`` option above. Named arguments can be passed by using either one of the following syntaxes:: # Similar to the command line management.call_command('dumpdata', '--natural') # Named argument similar to the command line minus the initial dashes and # with internal dashes replaced by underscores management.call_command('dumpdata', natural=True) # `use_natural_keys` is the option destination variable management.call_command('dumpdata', use_natural_keys=True) .. versionchanged:: 1.8 The first syntax is now supported thanks to management commands using the :py:mod:`argparse` module. For the second syntax, Django previously passed the option name as-is to the command, now it is always using the ``dest`` variable name (which may or may not be the same as the option name). Command options which take multiple options are passed a list:: management.call_command('dumpdata', exclude=['contenttypes', 'auth']) Loading docs/releases/1.8.txt +7 −0 Original line number Diff line number Diff line Loading @@ -196,6 +196,13 @@ Management Commands * :djadmin:`inspectdb` now outputs ``Meta.unique_together``. * When calling management commands from code through :ref:`call_command <call-command>` and passing options, the option name can match the command line option name (without the initial dashes) or the final option destination variable name, but in either case, the resulting option received by the command is now always the ``dest`` name specified in the command option definition (as long as the command uses the new :py:mod:`argparse` module). Models ^^^^^^ Loading tests/user_commands/management/commands/dance.py +2 −0 Original line number Diff line number Diff line Loading @@ -9,9 +9,11 @@ class Command(BaseCommand): def add_arguments(self, parser): parser.add_argument("-s", "--style", default="Rock'n'Roll") parser.add_argument("-x", "--example") parser.add_argument("--opt-3", action='store_true', dest='option3') def handle(self, *args, **options): example = options["example"] if example == "raise": raise CommandError() self.stdout.write("I don't feel like dancing %s." % options["style"]) self.stdout.write(','.join(options.keys())) tests/user_commands/tests.py +16 −4 Original line number Diff line number Diff line Loading @@ -15,14 +15,15 @@ class CommandTests(SimpleTestCase): def test_command(self): out = StringIO() management.call_command('dance', stdout=out) self.assertEqual(out.getvalue(), "I don't feel like dancing Rock'n'Roll.\n") self.assertIn("I don't feel like dancing Rock'n'Roll.\n", out.getvalue()) def test_command_style(self): out = StringIO() management.call_command('dance', style='Jive', stdout=out) self.assertEqual(out.getvalue(), "I don't feel like dancing Jive.\n") self.assertIn("I don't feel like dancing Jive.\n", out.getvalue()) # Passing options as arguments also works (thanks argparse) management.call_command('dance', '--style', 'Jive', stdout=out) self.assertIn("I don't feel like dancing Jive.\n", out.getvalue()) def test_language_preserved(self): out = StringIO() Loading Loading @@ -76,6 +77,17 @@ class CommandTests(SimpleTestCase): if current_path is not None: os.environ['PATH'] = current_path def test_call_command_option_parsing(self): """ When passing the long option name to call_command, the available option key is the option dest name (#22985). """ out = StringIO() management.call_command('dance', stdout=out, opt_3=True) self.assertIn("option3", out.getvalue()) self.assertNotIn("opt_3", out.getvalue()) self.assertNotIn("opt-3", out.getvalue()) def test_optparse_compatibility(self): """ optparse should be supported during Django 1.8/1.9 releases. Loading Loading
django/core/management/__init__.py +5 −1 Original line number Diff line number Diff line Loading @@ -102,8 +102,12 @@ def call_command(name, *args, **options): # Simulate argument parsing to get the option defaults (see #10080 for details). parser = command.create_parser('', name) if command.use_argparse: # Use the `dest` option name from the parser option opt_mapping = dict((sorted(s_opt.option_strings)[0].lstrip('-').replace('-', '_'), s_opt.dest) for s_opt in parser._actions if s_opt.option_strings) arg_options = dict((opt_mapping.get(key, key), value) for key, value in options.items()) defaults = parser.parse_args(args=args) defaults = dict(defaults._get_kwargs(), **options) defaults = dict(defaults._get_kwargs(), **arg_options) else: # Legacy optparse method defaults, _ = parser.parse_args(args=[]) Loading
docs/ref/django-admin.txt +18 −1 Original line number Diff line number Diff line Loading @@ -1824,10 +1824,27 @@ Examples:: management.call_command('loaddata', 'test_data', verbosity=0) Note that command options that take no arguments are passed as keywords with ``True`` or ``False``:: with ``True`` or ``False``, as you can see with the ``interactive`` option above. Named arguments can be passed by using either one of the following syntaxes:: # Similar to the command line management.call_command('dumpdata', '--natural') # Named argument similar to the command line minus the initial dashes and # with internal dashes replaced by underscores management.call_command('dumpdata', natural=True) # `use_natural_keys` is the option destination variable management.call_command('dumpdata', use_natural_keys=True) .. versionchanged:: 1.8 The first syntax is now supported thanks to management commands using the :py:mod:`argparse` module. For the second syntax, Django previously passed the option name as-is to the command, now it is always using the ``dest`` variable name (which may or may not be the same as the option name). Command options which take multiple options are passed a list:: management.call_command('dumpdata', exclude=['contenttypes', 'auth']) Loading
docs/releases/1.8.txt +7 −0 Original line number Diff line number Diff line Loading @@ -196,6 +196,13 @@ Management Commands * :djadmin:`inspectdb` now outputs ``Meta.unique_together``. * When calling management commands from code through :ref:`call_command <call-command>` and passing options, the option name can match the command line option name (without the initial dashes) or the final option destination variable name, but in either case, the resulting option received by the command is now always the ``dest`` name specified in the command option definition (as long as the command uses the new :py:mod:`argparse` module). Models ^^^^^^ Loading
tests/user_commands/management/commands/dance.py +2 −0 Original line number Diff line number Diff line Loading @@ -9,9 +9,11 @@ class Command(BaseCommand): def add_arguments(self, parser): parser.add_argument("-s", "--style", default="Rock'n'Roll") parser.add_argument("-x", "--example") parser.add_argument("--opt-3", action='store_true', dest='option3') def handle(self, *args, **options): example = options["example"] if example == "raise": raise CommandError() self.stdout.write("I don't feel like dancing %s." % options["style"]) self.stdout.write(','.join(options.keys()))
tests/user_commands/tests.py +16 −4 Original line number Diff line number Diff line Loading @@ -15,14 +15,15 @@ class CommandTests(SimpleTestCase): def test_command(self): out = StringIO() management.call_command('dance', stdout=out) self.assertEqual(out.getvalue(), "I don't feel like dancing Rock'n'Roll.\n") self.assertIn("I don't feel like dancing Rock'n'Roll.\n", out.getvalue()) def test_command_style(self): out = StringIO() management.call_command('dance', style='Jive', stdout=out) self.assertEqual(out.getvalue(), "I don't feel like dancing Jive.\n") self.assertIn("I don't feel like dancing Jive.\n", out.getvalue()) # Passing options as arguments also works (thanks argparse) management.call_command('dance', '--style', 'Jive', stdout=out) self.assertIn("I don't feel like dancing Jive.\n", out.getvalue()) def test_language_preserved(self): out = StringIO() Loading Loading @@ -76,6 +77,17 @@ class CommandTests(SimpleTestCase): if current_path is not None: os.environ['PATH'] = current_path def test_call_command_option_parsing(self): """ When passing the long option name to call_command, the available option key is the option dest name (#22985). """ out = StringIO() management.call_command('dance', stdout=out, opt_3=True) self.assertIn("option3", out.getvalue()) self.assertNotIn("opt_3", out.getvalue()) self.assertNotIn("opt-3", out.getvalue()) def test_optparse_compatibility(self): """ optparse should be supported during Django 1.8/1.9 releases. Loading