zmbq
zmbq

Reputation: 39013

Django's call_command fails with missing required arguments

I want to call a Django management command from one of my tests. I'm using django.core.management.call_command for this. And it doesn't work.

I have a command with 4 required arguments. When I call it, it complains all arguments are missing even though I'm passing them:

call_command('my_command', url='12', project='abc', website='zbb', title='12345')

I get the base command error that --url, --project, --website and --title are missing.

I did not specify a different destination for these arguments.

I looked at the call_command source and pinpointed the problem to the following line in call_command:

if command.use_argparse:
    # Use the `dest` option name from the parser option
    opt_mapping = {sorted(s_opt.option_strings)[0].lstrip('-').replace('-', '_'): s_opt.dest
                   for s_opt in parser._actions if s_opt.option_strings}
    arg_options = {opt_mapping.get(key, key): value for key, value in options.items()}
    defaults = parser.parse_args(args=args)    ****** THIS *****
    defaults = dict(defaults._get_kwargs(), **arg_options)
    # Move positional args out of options to mimic legacy optparse
    args = defaults.pop('args', ())

args is the positional arguments passed to call_commands, which is empty. I'm only passing named arguments. parser.parse_args complains the required variables are missing.

This is in Django 1.8.3.

Here is my command's add_arguments function (I just removed the help strings for brevity):

def add_arguments(self, parser):
    parser.add_argument('--url', action='store', required=True)
    parser.add_argument('--project', action='store', required=True)
    parser.add_argument('--continue-processing', action='store_true', default=False)
    parser.add_argument('--website', action='store', required=True)
    parser.add_argument('--title', action='store', required=True)
    parser.add_argument('--duplicate', action='store_true',default=False)

Upvotes: 6

Views: 2896

Answers (1)

hpaulj
hpaulj

Reputation: 231355

Based on that piece of code which you posted, I've concluded in call_command argument is required

that the required named arguments have to be passed in through *args, not just the positionals.

**kwargs bypasses the parser. So it doesn't see anything you defined there. **kwargs may override the *args values, but *args still needs something for each required argument. If you don't want to do that, then turn off the required attribute.

Upvotes: 3

Related Questions