如何建立自訂 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
在這個範例中,任何在 INSTALLED_APPS
中包含 polls
應用程式的專案都可以使用 closepoll
命令。
_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 dict 參數中可用。請參閱 argparse
Python 文件,以取得有關 add_argument
用法的更多資訊。
除了能夠新增自訂命令列選項之外,所有 管理命令都可以接受一些預設選項,例如 --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
,來在新的名稱下提供意外被覆寫的第三方應用程式的管理命令。
命令物件¶
所有管理命令最終都由此衍生而來的基礎類別。
如果您想要存取所有剖析命令列引數並找出要呼叫的回應程式碼的機制,請使用這個類別;如果您不需要變更任何行為,請考慮使用它的子類別之一。
子類化 BaseCommand
類別需要您實作 handle()
方法。
屬性¶
所有屬性都可以在您的衍生類別中設定,並可以在 BaseCommand
的子類別中使用。
- BaseCommand.help¶
命令的簡短描述,當使用者執行命令
python manage.py help <command>
時,將會列印在說明訊息中。
- 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 進行了一些自訂。您可以覆寫此方法並使用
ArgumentParser
參數的kwargs
呼叫super()
來客製化實例。
- BaseCommand.add_arguments(parser)[來源]¶
新增剖析器引數的進入點,以處理傳遞給命令的命令列引數。自訂命令應覆寫此方法,以新增命令接受的位置引數和可選引數。直接子類別化
BaseCommand
時,不需要呼叫super()
。
- 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()
。對於每個標籤,`handle_label()` 會被調用一次。
- LabelCommand.label¶
一個字串,描述傳遞給命令的任意參數。該字串會被用於命令的使用說明文字和錯誤訊息中。預設值為
'label'
。
- LabelCommand.handle_label(label, **options)¶
針對在命令行上給定的字串
label
執行命令的動作。
命令例外¶
例外類別,表示執行管理命令時發生問題。
如果從命令行控制台執行管理命令時引發此例外,它將被捕獲並轉換為格式良好的錯誤訊息輸出到適當的輸出流(即 stderr
)。因此,引發此例外(並提供錯誤的合理描述)是表示命令執行過程中發生錯誤的首選方式。它接受可選的 returncode
參數,以自訂管理命令退出的狀態碼,並使用 sys.exit()
退出。
如果管理命令是通過 call_command()
從程式碼中調用,則需要您在必要時捕獲例外。