可以在Django管理命令中创建子解析器吗? [英] Is it possible to create subparsers in a django management command?
本文介绍了可以在Django管理命令中创建子解析器吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
标题确实说明了一切,但我目前有这个,但它不起作用:
class Command(BaseCommand):
help = ("Functions related to downloading, parsing, and indexing the "
"content")
def add_arguments(self, parser):
subparsers = parser.add_subparsers()
download_parser = subparsers.add_parser(
'download',
help='Using a local CSV, download the XML data for content. '
'Output is sent to the log.'
)
download_parser.add_argument(
'--start_line',
type=int,
default=0,
help='The line in the file where you wish to start processing.'
)
# Add an argparse parser for parsing the content. Yes, this is
# a bit confusing.
content_parser_parser = subparsers.add_parser(
'parse',
help="Look at the file system and parse everything you see so that "
"we have content in the databse."
)
content_parser_parser.add_argument(
'--start_item',
type=int,
default=0,
help="Assuming the content is sorted by file name, this item is "
"the one to start on."
)
我的具体想法是创建一个有子命令的命令,用于下载XML内容或将其解析到数据库中。
推荐答案
Django 2.1及更高版本
在Django 2.1及更高版本中,添加子命令非常简单:
from django.core.management.base import BaseCommand
class Command(BaseCommand):
def add_arguments(self, parser):
subparsers = parser.add_subparsers(title="subcommands",
dest="subcommand",
required=True)
然后使用subparser
,就像编写使用argparse
的非Django应用程序一样。例如,如果需要名为foo
的子命令,则该子命令可能带有--bar
参数:
foo = subparsers.add_parser("foo")
foo.set_defaults(subcommand=fooVal)
foo.add_argument("--bar")
fooVal
值是您在用户指定foo
子命令时决定subcommand
选项应设置的值。我经常将其设置为Callable。
Django的旧版本
这是可能的,但需要做一些工作:
from django.core.management.base import BaseCommand, CommandParser
class Command(BaseCommand):
[...]
def add_arguments(self, parser):
cmd = self
class SubParser(CommandParser):
def __init__(self, **kwargs):
super(SubParser, self).__init__(cmd, **kwargs)
subparsers = parser.add_subparsers(title="subcommands",
dest="subcommand",
required=True,
parser_class=SubParser)
当您调用add_subparsers
时,默认情况下argparse
会创建一个新的解析器,该解析器与调用add_subparser
的解析器属于同一类。碰巧您在parser
中获得的解析器是一个CommandParser
实例(在django.core.management.base中定义)。CommandParser
类在**kwargs
之前需要cmd
参数(而argparse
提供的默认解析器类只接受**kwargs
):
def __init__(self, cmd, **kwargs):
因此,当您尝试添加子解析器时,它会失败,因为仅使用**kwargs
调用构造函数,并且缺少cmd
参数。
上面的代码通过传入parser_class
参数来修复此问题。
注意事项:
在上面的代码中,我创建了一个新类,因为
parser_class
这个名称表明应该传递给它的是一个真正的类。然而,这也是可行的:
目前我还没有遇到任何问题,但未来对def add_arguments(self, parser): cmd = self subparsers = parser.add_subparsers( title="subcommands", dest="subcommand", required=True, parser_class=lambda **kw: CommandParser(cmd, **kw))
argparse
的更改可能会导致使用lambda而不是真正的类失败。由于该参数名为parser_class
,而不是parser_maker
或parser_manufacture
,我认为这样的更改是公平的。/li>难道我们不能只传递一个常用的
argparse
类,而不是传递parser_class
中的一个自定义类吗?不会有直接的问题,但会有意外的后果。CommandParser
中的注释表明argparse
的条形解析器的行为不适合Django命令。尤其是类的docstring声明:""" Customized ArgumentParser class to improve some error messages and prevent SystemExit in several occasions, as SystemExit is unacceptable when a command is called programmatically. """
这是Jerzyk's answer遇到的问题。此处的解决方案通过派生
CommandParser
避免了该问题,从而提供了Django所需的正确行为。
这篇关于可以在Django管理命令中创建子解析器吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文