标题确实说明了一切,但我目前有这个,但它不起作用:
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
是你决定的subcommand
当用户指定 foo
时,选项应设置为子命令。我经常将它设置为可调用的。旧版本的 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
类(class) 需要 一个 cmd
**kwargs
之前的参数(而 argparse
提供的默认解析器类只需要 **kwargs
):def __init__(self, cmd, **kwargs):
因此,当您尝试添加子解析器时,它会失败,因为仅使用
**kwargs
调用构造函数和 cmd
论据不见了。上面的代码通过传入
parser_class
解决了这个问题。 argument 一个添加缺失参数的类。需要考虑的事项:
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))
现在我没有遇到任何问题,但 future 可能会更改为
argparse
可能会使使用 lambda 而不是真正的类失败。由于参数被称为 parser_class
而不是 parser_maker
或 parser_manufacture
我认为这样的改变是公平的游戏。 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 - 是否可以在 django 管理命令中创建子解析器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36706220/