django 1.8 官方文檔翻譯: 6-4-2 編寫自定義的django-admin命令

編寫自定義的django-admin命令

應用能夠經過manage.py註冊它們本身的動做。例如,你可能想爲你正在發佈的Django應用添加一個manage.py動做。在本頁文檔中,咱們將爲教程中的 polls應用構建一個自定義的 closepoll命令。html

要作到這點,只需向該應用添加一個management/commands目錄。Django將爲該目錄中名字沒有如下劃線開始的每一個Python模塊註冊一個manage.py命令。例如:python

polls/
    __init__.py
    models.py
    management/
        __init__.py
        commands/
            __init__.py
            _private.py
            closepoll.py
    tests.py
    views.py

在Python 2上,請確保managementmanagement/commands兩個目錄都包含__init__.py 文件,不然將檢測不到你的命令。數據庫

在這個例子中,closepoll命令對任何項目均可使用,只要它們在INSTALLED_APPS裏包含polls應用。django

_private.py將不能夠做爲一個管理命令使用。app

closepoll.py模塊只有一個要求 – 它必須定義一個Command類並擴展自BaseCommand或其 子類。框架

獨立的腳本函數

自定義的管理命令主要用於運行獨立的腳本或者UNIX crontab和Windows週期任務控制面板週期性執行的腳本。測試

要實現這個命令,需將polls/management/commands/closepoll.py編輯成這樣:ui

from django.core.management.base import BaseCommand, CommandError
from polls.models import Poll

class Command(BaseCommand):
    help = 'Closes the specified poll for voting'

    def add_arguments(self, parser):
        parser.add_argument('poll_id', nargs='+', type=int)

    def handle(self, *args, **options):
        for poll_id in options['poll_id']:
            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('Successfully closed poll "%s"' % poll_id)
Changed in Django 1.8:

在Django 1.8以前,管理命令基於optparse模塊,位置參數傳遞給*args,可選參數傳遞給**options。如今,管理命令使用argparse解析參數,默認全部的參數都傳遞給**options,除非你命名你的位置參數爲args(兼容模式)。對於新的命令,鼓勵你僅僅使用**options。

this

當你使用管理命令並但願提供控制檯輸出時,你應該寫到self.stdoutself.stderr,而不能直接打印到 stdoutstderr。經過使用這些代理方法,測試你自定義的命令將變得很是容易。還請注意,你不須要在消息的末尾加上一個換行符,它將被自動添加,除非你指定ending參數:

self.stdout.write("Unterminated line", ending='')

新的自定義命令可使用python manage.py closepoll <poll_id>調用。

handle()接收一個或多個poll_ids併爲他們中的每一個設置 poll.openedFalse。若是用戶訪問任何不存在的polls,將引起一個CommandErrorpoll.opened屬性在教程中並不存在,只是爲了這個例子將它添加到polls.models.Poll中。

接收可選參數

經過接收額外的命令行選項,能夠簡單地修改closepoll來刪除一個給定的poll而不是關閉它。這些自定義的選項能夠像下面這樣添加到 add_arguments()方法中:

class Command(BaseCommand):
    def add_arguments(self, parser):
        # Positional arguments
        parser.add_argument('poll_id', nargs='+', type=int)

        # Named (optional) arguments
        parser.add_argument('--delete',
            action='store_true',
            dest='delete',
            default=False,
            help='Delete poll instead of closing it')

    def handle(self, *args, **options):
        # ...
        if options['delete']:
            poll.delete()
        # ...
Changed in Django 1.8:

以前,只支持標準的optparse庫,你必須利用optparse.make_option()擴展命令option_list變量。

選項(在咱們的例子中爲delete)在handle方法的options字典參數中能夠訪問到。更多關於add_argument用法的信息,請參考argparse的Python 文檔。

除了能夠添加自定義的命令行選項, 管理命令還能夠接收一些默認的選項,例如--verbosity--traceback

管理命令和區域設置

默認狀況下,BaseCommand.execute()方法使轉換失效,由於某些與Django一塊兒的命令完成的任務要求一個與項目無關的語言字符串(例如,面向用戶的內容渲染和數據庫填入)。

Changed in Django 1.8:

在以前的版本中,Django強制使用"en-us"區域設置而不是使轉換失效。

若是,出於某些緣由,你的自定義的管理命令須要使用一個固定的區域設置,你須要在你的handle()方法中利用I18N支持代碼提供的函數手工地啓用和停用它:

from django.core.management.base import BaseCommand, CommandError
from django.utils import translation

class Command(BaseCommand):
    ...
    can_import_settings = True

    def handle(self, *args, **options):

        # Activate a fixed locale, e.g. Russian
        translation.activate('ru')

        # Or you can activate the LANGUAGE_CODE # chosen in the settings:
        from django.conf import settings
        translation.activate(settings.LANGUAGE_CODE)

        # Your command logic here
        ...

        translation.deactivate()

另外一個須要多是你的命令只是簡單地應該使用設置中設置的區域設置且Django應該保持不讓它停用。你可使用BaseCommand.leave_locale_alone選項實現這個功能。

雖然上面描述的場景能夠工做,可是考慮到系統管理命令對於運行非統一的區域設置一般必須很是當心,因此你可能須要:

  • 確保運行命令時USE_I18N設置永遠爲True(this is a good example of the potential problems stemming from a dynamic runtime environment that Django commands avoid offhand by deactivating translations)。

  • Review the code of your command and the code it calls for behavioral differences when locales are changed and evaluate its impact on predictable behavior of your command.

測試

關於如何測試自定義管理命令的信息能夠在測試文檔中找到。

Command 對象

class BaseCommand

全部管理命令最終繼承的基類。

若是你想得到解析命令行參數並在響應中如何調用代碼的全部機制,可使用這個類;若是你不須要改變這個行爲,請考慮使用它的子類。

繼承BaseCommand類要求你實現handle()方法。

屬性

全部的屬性均可以在你派生的類中設置,並在BaseCommand的子類中使用。

BaseCommand.args

一個字符串,列出命令接收的參數,適合用於幫助信息;例如,接收一個應用名稱列表的命令能夠設置它爲‘<app_label app_label ...>’。

Deprecated since version 1.8:

如今,應該在add_arguments()方法中完成,經過調用parser.add_argument()方法。參見上面的closepoll例子。

BaseCommand.can_import_settings

一個布爾值,指示該命令是否須要導入Django的設置的能力;若是爲Trueexecute()將在繼續以前驗證這是否可能。默認值爲True

BaseCommand.help

命令的簡短描述,當用戶運行python manage.py help <command>命令時將在幫助信息中打印出來。

BaseCommand.missing_args_message

New in Django 1.8.

若是你的命令定義了必需的位置參數,你能夠自定義參數缺失時返回的錯誤信息。默認是由argparse輸出的 (「too few arguments」)。

BaseCommand.option_list

這是optparse選項列表,將賦值給命令的OptionParser用於解析命令。

Deprecated since version 1.8:

如今,你應該覆蓋`add_arguments()`方法來添加命令行接收的自定義參數。參見上面的例子。

BaseCommand.output_transaction

一個布爾值,指示命令是否輸出SQL語句;若是爲True,輸出將被自動用BEGIN;COMMIT;封裝。默認爲False

BaseCommand.requires_system_checks

New in Django 1.7.

一個布爾值;若是爲True,在執行該命令以前將檢查整個Django項目是否有潛在的問題。若是requires_system_checks缺失,則使用requires_model_validation的值。若是後者的值也缺失,則使用默認值(True)。同時定義requires_system_checksrequires_model_validation將致使錯誤。

BaseCommand.requires_model_validation

Deprecated since version 1.7:

被requires_system_checks代替

一個布爾值;若是爲True,將在執行命令以前做安裝的模型的驗證。默認爲True。若要驗證一個單獨應用的模型而不是所有應用的模型,能夠調用在handle()中調用validate()

BaseCommand.leave_locale_alone

一個布爾值,指示設置中的區域設置在執行命令過程當中是否應該保持而不是強制設成‘en-us’。

默認值爲False

若是你決定在你自定義的命令中修改該選項的值,請確保你知道你正在作什麼。 若是它建立對區域設置敏感的數據庫內容,這種內容不該該包含任何轉換(好比django.contrib.auth權限發生的狀況),由於將區域設置變成與實際上默認的‘en-us’ 不一樣可能致使意外的效果。更進一步的細節參見上面的管理命令和區域設置一節。

can_import_settings選項設置爲False時,該選項不能夠也爲False,由於嘗試設置區域設置須要訪問settings。這種狀況將產生一個CommandError

方法

BaseCommand有幾個方法能夠被覆蓋,可是隻有handle()是必須實現的。

在子類中實現構造函數

若是你在BaseCommand的子類中實現__init__,你必須調用BaseCommand__init__

class Command(BaseCommand):
    def __init__(self, *args, **kwargs):
        super(Command, self).__init__(*args, **kwargs)
        # ...

BaseCommand.add_arguments(parser)

New in Django 1.8.

添加解析器參數的入口,以處理傳遞給命令的命令行參數。自定義的命令應該覆蓋這個方法以添加命令行接收的位置參數和可選參數。當直接繼承BaseCommand時不須要調用super()

BaseCommand.get_version()

返回Django的版本,對於全部內建的Django命令應該都是正確的。用戶提供的命令能夠覆蓋這個方法以返回它們本身的版本。

BaseCommand.execute(*args, **options)

執行這個命令,若是須要則做系統檢查(經過 requires_system_checks屬性控制)。若是該命令引起一個CommandError,它將被截斷並打印到標準錯誤輸出。

在你的代碼中調用管理命令

不該該在你的代碼中直接調用execute()來執行一個命令。請使用call_command

BaseCommand.handle(*args, **options)

命令的真正邏輯。子類必須實現這個方法。

BaseCommand.check(app_configs=None, tags=None, display_num_errors=False)

New in Django 1.7.

利用系統的檢測框架檢測所有Django項目的潛在問題。嚴重的問題將引起CommandError;警告會輸出到標準錯誤輸出;次要的通知會輸出到標準輸出。

若是app_configstags都爲None,將進行全部的系統檢查。tags能夠是一個要檢查的標籤列表,好比compatibilitymodels

BaseCommand.validate(app=None, display_num_errors=False)

Deprecated since version 1.7:

被check命令代替

若是appNone,那麼將檢查安裝的全部應用的錯誤。

BaseCommand 的子類

class AppCommand

這個管理命令接收一個或多個安裝的應用標籤做爲參數,並對它們每個都作一些動做。

子類不用實現handle(),但必須實現handle_app_config(),它將會爲每一個應用調用一次。

AppCommand.handle_app_config(app_config, **options)

app_config完成命令行的動做,其中app_configAppConfig的實例,對應於在命令行上給出的應用標籤。

Changed in Django 1.7:

之前,AppCommand子類必須實現handle_app(app, **options),其中app是一個模型模塊。新的API能夠不須要模型模塊來處理應用。遷移的最快的方法以下:

def handle_app_config(app_config, **options):
    if app_config.models_module is None:
        return                                  # Or raise an exception.
    app = app_config.models_module
    # Copy the implementation of handle_app(app_config, **options) here.

然而,你能夠經過直接使用app_config的屬性來簡化實現。

class LabelCommand

這個管理命令接收命令行上的一個或多個參數(標籤),並對它們每個都作一些動做。

子類不用實現handle(),但必須實現handle_label(),它將會爲每一個標籤調用一次。

LabelCommand.handle_label(label, **options)

label完成命令行的動做,label是命令行給出的字符串。

class NoArgsCommand

Deprecated since version 1.8:

使用BaseCommand代替,它默認也不須要參數。

這個命令不接收命令行上的參數。

子類不須要實現handle(),但必須實現handle_noargs()handle()自己已經被覆蓋以保證不會有參數傳遞給命令。

NoArgsCommand.handle_noargs(**options)

完成這個命令的動做

Command 的異常

class CommandError

異常類,表示執行一個管理命令時出現問題。

若是這個異常是在執行一個來自命令行控制檯的管理命令時引起,它將被捕獲並轉換成一個友好的錯誤信息到合適的輸出流(例如,標準錯誤輸出);所以,引起這個異常(並帶有一個合理的錯誤描述)是首選的方式來指示在執行一個命令時某些東西出現錯誤。

若是管理命令從代碼中經過call_command調用,那麼須要時捕獲這個異常由你決定。

譯者:Django 文檔協做翻譯小組,原文:Adding custom commands

本文以 CC BY-NC-SA 3.0 協議發佈,轉載請保留做者署名和文章出處。

Django 文檔協做翻譯小組人手緊缺,有興趣的朋友能夠加入咱們,徹底公益性質。交流羣:467338606。

相關文章
相關標籤/搜索