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
如果您正在编写一个使用以下内容的非 Django 应用程序,您也会这样做argparse https://docs.python.org/3/library/argparse.html。例如,如果您想要一个名为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
is a CommandParser
实例(定义于django.core.management.base https://github.com/django/django/blob/0d3c616fbb2f49fa7ff6809e5a6777275352b35b/django/core/management/base.py#L43). The CommandParser
class requires a 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))
目前我还没有遇到任何问题,但将来可能会更改为argparse
可能会导致使用 lambda 而不是真正的类失败。由于该参数被称为parser_class
而不是类似的东西parser_maker
or parser_manufacture
我认为这样的改变是公平的。
-
我们不能只传递其中一只股票吗argparse
类而不是传递自定义类parser_class
?就不会有即时问题,但会产生意想不到的后果。中的评论CommandParser
表明 的行为argparse
的 Stick 解析器对于 Django 命令来说是不可取的。特别是,文档字符串 https://github.com/django/django/blob/122c90a43b2486bf278def8f068b6d1cebaa66f9/django/core/management/base.py#L44对于班级状态:
"""
Customized ArgumentParser class to improve some error messages and prevent
SystemExit in several occasions, as SystemExit is unacceptable when a
command is called programmatically.
"""
这是一个问题杰兹克的回答 https://stackoverflow.com/users/646765/jerzyk患有。这里的解决方案通过派生来避免这个问题CommandParser
从而提供 Django 所需的正确行为。