如何创建自定义 django-admin
命令¶
应用程序可以使用 manage.py
注册自己的操作。例如,你可能希望为正在分发的 Django 应用程序添加一个 manage.py
操作。在本指南中,我们将为 教程中的 polls
应用程序构建一个自定义 closepoll
命令。
为此,请将 management/commands
目录添加到应用程序。Django 将为该目录中名称不以下划线开头的每个 Python 模块注册一个 manage.py
命令。例如
polls/
__init__.py
models.py
management/
__init__.py
commands/
__init__.py
_private.py
closepoll.py
tests.py
views.py
在此示例中, closepoll
命令将对任何在 INSTALLED_APPS
中包含 polls
应用程序的项目可用。
模块 _private.py
将不可用作管理命令。
模块 closepoll.py
只有一个要求——它必须定义一个扩展 BaseCommand
或其 子类 之一的类 Command
。
独立脚本
自定义管理命令对于运行独立脚本或定期从 UNIX crontab 或 Windows 计划任务控制面板执行的脚本特别有用。
要实现命令,请编辑 polls/management/commands/closepoll.py
,使其如下所示
from django.core.management.base import BaseCommand, CommandError
from polls.models import Question as Poll
class Command(BaseCommand):
help = "Closes the specified poll for voting"
def add_arguments(self, parser):
parser.add_argument("poll_ids", nargs="+", type=int)
def handle(self, *args, **options):
for poll_id in options["poll_ids"]:
try:
poll = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise CommandError('Poll "%s" does not exist' % poll_id)
poll.opened = False
poll.save()
self.stdout.write(
self.style.SUCCESS('Successfully closed poll "%s"' % poll_id)
)
注意
当您使用管理命令并希望提供控制台输出时,您应该写入 self.stdout
和 self.stderr
,而不是直接打印到 stdout
和 stderr
。通过使用这些代理,测试您的自定义命令变得更加容易。还要注意,您不必以换行符结尾消息,它将自动添加,除非您指定 ending
参数
self.stdout.write("Unterminated line", ending="")
可以使用 python manage.py closepoll <poll_ids>
调用新的自定义命令。
方法 handle()
采用一个或多个 poll_ids
,并将每个 poll.opened
设置为 False
。如果用户引用了任何不存在的投票,则会引发 CommandError
。属性 poll.opened
在 教程 中不存在,并已添加到 polls.models.Question
中以供本示例使用。
接受可选参数¶
同样的 closepoll
可以轻松修改,通过接受附加命令行选项来删除给定的投票,而不是关闭它。这些自定义选项可以像这样添加到 add_arguments()
方法中
class Command(BaseCommand):
def add_arguments(self, parser):
# Positional arguments
parser.add_argument("poll_ids", nargs="+", type=int)
# Named (optional) arguments
parser.add_argument(
"--delete",
action="store_true",
help="Delete poll instead of closing it",
)
def handle(self, *args, **options):
# ...
if options["delete"]:
poll.delete()
# ...
选项(在我们的示例中为 delete
)在 handle 方法的 options 字典参数中可用。有关 add_argument
用法的更多信息,请参阅 argparse
Python 文档。
除了能够添加自定义命令行选项之外,所有 管理命令 都可以接受一些默认选项,例如 --verbosity
和 --traceback
。
管理命令和语言环境¶
默认情况下,管理命令使用当前活动语言环境执行。
如果由于某种原因,您的自定义管理命令必须在没有活动语言环境的情况下运行(例如,为了防止翻译内容插入到数据库中),请使用 @no_translations
装饰器在 handle()
方法上停用翻译
from django.core.management.base import BaseCommand, no_translations
class Command(BaseCommand):
...
@no_translations
def handle(self, *args, **options): ...
由于停用翻译需要访问已配置的设置,因此该装饰器不能用于在没有已配置设置的情况下工作的命令。
覆盖命令¶
Django 注册内置命令,然后在 INSTALLED_APPS
中反向搜索命令。在搜索过程中,如果命令名称与已注册的命令重复,则新发现的命令将覆盖第一个命令。
换句话说,要覆盖命令,新命令必须具有相同的名称,并且其应用必须在 INSTALLED_APPS
中位于被覆盖命令的应用之前。
可以通过在项目的某个应用(在 INSTALLED_APPS
中按顺序位于第三方应用之前)中创建新命令来让无意中被覆盖的第三方应用的管理命令在新名称下可用,该命令导入被覆盖命令的 Command
。
命令对象¶
-
class
BaseCommand
¶
所有管理命令最终派生的基类。
如果您希望访问解析命令行参数和确定响应时要调用的代码的所有机制,请使用此类;如果您不需要更改任何行为,请考虑使用其 子类 之一。
对 BaseCommand
类进行子类化要求您实现 handle()
方法。
属性¶
所有属性都可以在派生类中设置,并可以在 BaseCommand
的 子类 中使用。
-
BaseCommand.
help
¶ 命令的简短描述,当用户运行命令
python manage.py help <command>
时,该描述将打印在帮助消息中。
-
BaseCommand.
missing_args_message
¶ 如果您的命令定义了强制性的位置参数,则可以在缺少参数的情况下自定义返回的消息错误。默认值由
argparse
输出(“参数太少”)。
-
BaseCommand.
output_transaction
¶ 指示命令是否输出 SQL 语句的布尔值;如果为
True
,输出将自动用BEGIN;
和COMMIT;
包装。默认值为False
。
-
BaseCommand.
requires_migrations_checks
¶ 布尔值;如果为
True
,则当磁盘上的迁移集合与数据库中的迁移不匹配时,命令会打印警告。警告不会阻止命令执行。默认值为False
。
-
BaseCommand.
requires_system_checks
¶ 标签列表或元组,例如
[Tags.staticfiles, Tags.models]
。在所选标签中注册的系统检查将在执行命令之前检查错误。值'__all__'
可用于指定应执行所有系统检查。默认值为'__all__'
。
-
BaseCommand.
style
¶ 写入
stdout
或stderr
时有助于创建彩色输出的实例属性。例如self.stdout.write(self.style.SUCCESS("..."))
请参阅语法着色以了解如何修改调色板以及查看可用样式(使用该部分中描述的“角色”的大写版本)。
如果您在运行命令时传递了
--no-color
选项,所有self.style()
调用都将返回未着色的原始字符串。
-
BaseCommand.
suppressed_base_arguments
¶ 在帮助输出中要禁止的默认命令选项。这应为一组选项名称(例如
'--verbosity'
)。仍然会传递禁止选项的默认值。
方法¶
BaseCommand
有几个可被覆盖的方法,但只有 handle()
方法必须实现。
在子类中实现构造函数
如果您在 BaseCommand
的子类中实现了 __init__
,则必须调用 BaseCommand
的 __init__
class Command(BaseCommand):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# ...
-
BaseCommand.
create_parser
(prog_name, subcommand, **kwargs)¶ 返回一个
CommandParser
实例,它是ArgumentParser
子类,针对 Django 进行了少量自定义。你可以通过覆盖此方法并使用
kwargs
调用super()
来自定义实例,其中包含ArgumentParser
参数。
-
BaseCommand.
add_arguments
(parser)¶ 添加解析器参数以处理传递给命令的命令行参数的入口点。自定义命令应覆盖此方法以添加命令接受的定位参数和可选参数。直接子类化
BaseCommand
时,不需要调用super()
。
-
BaseCommand.
get_version
()¶ 返回 Django 版本,这对于所有内置的 Django 命令都是正确的。用户提供的命令可以覆盖此方法以返回自己的版本。
-
BaseCommand.
execute
(*args, **options)¶ 尝试执行此命令,在需要时执行系统检查(由
requires_system_checks
属性控制)。如果命令引发CommandError
,它将被拦截并打印到stderr
。
在你的代码中调用管理命令
execute()
不应从你的代码中直接调用来执行命令。请使用 call_command()
。
-
BaseCommand.
handle
(*args, **options)¶ 命令的实际逻辑。子类必须实现此方法。
它可能会返回一个字符串,该字符串将打印到
stdout
(如果output_transaction
为True
,则用BEGIN;
和COMMIT;
包裹)。
-
BaseCommand.
check
(app_configs=None, tags=None, display_num_errors=False, include_deployment_checks=False, fail_level=checks.ERROR, databases=None)¶ 使用系统检查框架检查整个 Django 项目是否存在潜在问题。严重问题将作为
CommandError
提出;警告将输出到stderr
;次要通知将输出到stdout
。如果
app_configs
和tags
均为None
,则执行所有系统检查,但部署和数据库相关检查除外。tags
可以是检查标签列表,例如compatibility
或models
。你可以传递
include_deployment_checks=True
来执行部署检查,并在databases
中列出数据库别名列表,以针对它们运行数据库相关检查。
BaseCommand
子类¶
-
class
AppCommand
¶
一个管理命令,它将一个或多个已安装的应用程序标签作为参数,并对每个标签执行某些操作。
子类必须实现 handle_app_config()
,而不是实现 handle()
,该方法将针对每个应用程序调用一次。
-
AppCommand.
handle_app_config
(app_config, **options)¶ 对
app_config
执行命令操作,它将是与命令行中给出的应用程序标签相对应的AppConfig
实例。
-
class
LabelCommand
¶
一个管理命令,它在命令行中采用一个或多个任意参数(标签),并对每个参数执行某些操作。
子类必须实现 handle_label()
,而不是实现 handle()
,该方法将针对每个标签调用一次。
-
LabelCommand.
label
¶ 一个描述传递给命令的任意参数的字符串。该字符串用于命令的用法文本和错误消息中。默认为
'label'
。
-
LabelCommand.
handle_label
(label, **options)¶ 对
label
执行命令操作,它将是命令行中给出的字符串。
命令异常¶
-
异常
CommandError
(returncode=1)¶
在执行管理命令时指示存在问题的异常类。
如果在从命令行控制台执行管理命令期间引发此异常,它将被捕获并转换为针对适当输出流(即 stderr
)的格式良好的打印错误消息;因此,引发此异常(并附有错误的合理描述)是指示命令执行过程中出现问题的方式。它接受可选的 returncode
参数,以使用 sys.exit()
自定义管理命令退出的退出状态。
如果通过 call_command()
从代码中调用管理命令,则由你决定在需要时捕获异常。