django.core.management-command

17612 ワード

    1. ``django-admin`` or ``manage.py`` loads the command class
       and calls its ``run_from_argv()`` method.

    2. The ``run_from_argv()`` method calls ``create_parser()`` to get
       an ``ArgumentParser`` for the arguments, parses them, performs
       any environment changes requested by options like
       ``pythonpath``, and then calls the ``execute()`` method,
       passing the parsed arguments.

    3. The ``execute()`` method attempts to carry out the command by
       calling the ``handle()`` method with the parsed arguments; any
       output produced by ``handle()`` will be printed to standard
       output and, if the command is intended to produce a block of
       SQL statements, will be wrapped in ``BEGIN`` and ``COMMIT``.

    4. If ``handle()`` or ``execute()`` raised any exception (e.g.
       ``CommandError``), ``run_from_argv()`` will  instead print an error
       message to ``stderr``.

これはコマンド実行のプロセスです.
  • まずimport対応のcommandクラスをimportし、run_を呼び出します.from_Argv()がsysに入る.argvをパラメータとする.
  • create_を呼び出しますparser()メソッド、parserを返します.
  • パラメータを解析し、解析後のパラメータをexecute()メソッドに入力します.
  • はhandle()を実行し、返された結果を出力します.

  • 最初のステップは後で話しますが、今は主に後で処理するプロセスコードを見て、BaseCommandによって実現されています.
    BaseCommandクラスの実装コードが多いので,対応するメソッドを選択して解析する.
    def run_from_argv(self, argv):
            """
            Set up any environment changes requested (e.g., Python path
            and Django settings), then run this command. If the
            command raises a ``CommandError``, intercept it and print it sensibly
            to stderr. If the ``--traceback`` option is present or the raised
            ``Exception`` is not ``CommandError``, raise it.
            """
            self._called_from_command_line = True
            parser = self.create_parser(argv[0], argv[1])
    
            if self.use_argparse:
                options = parser.parse_args(argv[2:])
                cmd_options = vars(options)
                # Move positional args out of options to mimic legacy optparse
                args = cmd_options.pop('args', ())
            else:
                options, args = parser.parse_args(argv[2:])
                cmd_options = vars(options)
            handle_default_options(options)
            try:
                self.execute(*args, **cmd_options)
            except Exception as e:
                if options.traceback or not isinstance(e, CommandError):
                    raise
    
                # SystemCheckError takes care of its own formatting.
                if isinstance(e, SystemCheckError):
                    self.stderr.write(str(e), lambda x: x)
                else:
                    self.stderr.write('%s: %s' % (e.__class__.__name__, e))
                sys.exit(1)

    run_from_argv()はまずparser=selfを呼び出す.create_parser(argv[0],argv[1])メソッド.
    parserを得る後、selfを判断する.use_argparseで、返されるタイプを決定します.現在、2つの解析パラメータの方法があるため、1つはoptparseであり、django 2になる.0後に廃棄します.もう1つはargparserです.これは互換性を後方に保つためです.
    argvパラメータフォーマットはsys.argv、コマンド実行時のパラメータ.例:python manage runserver 0.0.0.0:8000
    ではargv=['manage','runserver','0.0.0.0:8000']である.
    今createを見てparserメソッドの具体的なコード.
    def create_parser(self, prog_name, subcommand):
            """
            Create and return the ``ArgumentParser`` which will be used to
            parse the arguments to this command.
    
            """
            if not self.use_argparse:
                # Backwards compatibility: use deprecated optparse module
                warnings.warn("OptionParser usage for Django management commands "
                              "is deprecated, use ArgumentParser instead",
                              RemovedInDjango20Warning)
                parser = OptionParser(prog=prog_name,
                                    usage=self.usage(subcommand),
                                    version=self.get_version())
                parser.add_option('-v', '--verbosity', action='store', dest='verbosity', default='1',
                    type='choice', choices=['0', '1', '2', '3'],
                    help='Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output')
                parser.add_option('--settings',
                    help=(
                        'The Python path to a settings module, e.g. '
                        '"myproject.settings.main". If this isn\'t provided, the '
                        'DJANGO_SETTINGS_MODULE environment variable will be used.'
                    ),
                )
                parser.add_option('--pythonpath',
                    help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".'),
                parser.add_option('--traceback', action='store_true',
                    help='Raise on CommandError exceptions')
                parser.add_option('--no-color', action='store_true', dest='no_color', default=False,
                    help="Don't colorize the command output.")
                for opt in self.option_list:
                    parser.add_option(opt)
            else:
                parser = CommandParser(self, prog="%s %s" % (os.path.basename(prog_name), subcommand),
                    description=self.help or None)
                parser.add_argument('--version', action='version', version=self.get_version())
                parser.add_argument('-v', '--verbosity', action='store', dest='verbosity', default='1',
                    type=int, choices=[0, 1, 2, 3],
                    help='Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output')
                parser.add_argument('--settings',
                    help=(
                        'The Python path to a settings module, e.g. '
                        '"myproject.settings.main". If this isn\'t provided, the '
                        'DJANGO_SETTINGS_MODULE environment variable will be used.'
                    ),
                )
                parser.add_argument('--pythonpath',
                    help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".')
                parser.add_argument('--traceback', action='store_true',
                    help='Raise on CommandError exceptions')
                parser.add_argument('--no-color', action='store_true', dest='no_color', default=False,
                    help="Don't colorize the command output.")
                if self.args:
                    # Keep compatibility and always accept positional arguments, like optparse when args is set
                    parser.add_argument('args', nargs='*')
                self.add_arguments(parser)
            return parser

    まずselfを判断する.use_argparse,
    @property
        def use_argparse(self):
            return not bool(self.option_list)

    判断によりoption_リスト属性Noが空、option_ListはBaseCommandクラスで、デフォルトは空の元祖です.
    option_list = ()

    djangoは現在argpaseを使用する傾向にあるため,ここではargparseを使用する部分についてのみ説明する.
    ここにまた新しいクラスCommandParserが現れました.
    class CommandParser(ArgumentParser):
        """
        Customized ArgumentParser class to improve some error messages and prevent
        SystemExit in several occasions, as SystemExit is unacceptable when a
        command is called programmatically.
        """
        def __init__(self, cmd, **kwargs):
            self.cmd = cmd
            super(CommandParser, self).__init__(**kwargs)
    
        def parse_args(self, args=None, namespace=None):
            # Catch missing argument for a better error message
            if (hasattr(self.cmd, 'missing_args_message') and
                    not (args or any(not arg.startswith('-') for arg in args))):
                self.error(self.cmd.missing_args_message)
            return super(CommandParser, self).parse_args(args, namespace)
    
        def error(self, message):
            if self.cmd._called_from_command_line:
                super(CommandParser, self).error(message)
            else:
                raise CommandError("Error: %s" % message)

    CommandParserはparseを書き直しただけだargs法.missing_を追加args_Messageの場合.
    パラメータが欠けている場合をどのように判断しますか?
    not (args or any(not arg.startswith('-') for arg in args))

    この文をtrueに戻すと、パラメータが欠けていることを示します.
    では
    args or any(not arg.startswith('-') for arg in args)

    falseに戻るべきです.ここでorオペレータを使用し、argsが空でなければargsを返すと、前の文はtrueを返すことになります.
    argsが空の場合は、後ろの
    any(not arg.startswith('-') for arg in args)

    .ではargs=()、
    not arg.startswith('-') for arg in args)

    戻るのは相変わらず()で、これでは意味がありません.
    error()メソッドも書き換え,放出異常を変えるだけである.
    self.cmd._called_from_command_line,run_from_args()は直接trueに割り当てられます.
    次にcreateを見てみましょうparserメソッド、CommandParserをインスタンス化した後、'--version'、'--verbosity'、'--settings'、'--pythonpath'、'--traceback'、'--no-color'オプションパラメータを追加します.
    注意してargsという属性はself.argsが空でない場合、後続のパラメータはargsに収集されます.
    parser.add_argument('args', nargs='*')

    これは互換性を後方に保つために設定されています.argsプロパティを設定と、後続のselfになります.add_Arguments(parser)は機能しません.
    def add_arguments(self, parser):
            """
            Entry point for subclassed commands to add custom arguments.
            """
            pass

    add_Arguments()メソッドは、カスタムパラメータを追加するためにサブクラスで実装されます.
    今run_に戻りますfrom_argv()メソッドでは,parserを作成すると解析パラメータとなる.
    options = parser.parse_args(argv[2:])
    cmd_options = vars(options)
    # Move positional args out of options to mimic legacy optparse
    args = cmd_options.pop('args', ())

    varsは、返されるNameSpaceオブジェクトoptionsを辞書cmd_に変換します.options .
    argsというパラメータを単独で提案した.
    次にhandle_を呼び出すdefault_options(options)メソッド.
    def handle_default_options(options):
        """
        Include any default options that all commands should accept here
        so that ManagementUtility can handle them before searching for
        user commands.
    
        """
        if options.settings:
            os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
        if options.pythonpath:
            sys.path.insert(0, options.pythonpath)

    主にsettingsとpythonpathの2つのパラメータの処理を担当します.settings環境変数DJANGO_を変更することでプロファイルを作成SETTINGS_MODULE.pythonpathはsysを介してパケットとモジュールを検索するパスを追加する.path変数が変わります.
    次にselfを呼び出す.execute(*args,**cmd_options)メソッド.
    def execute(self, *args, **options):
            """
            Try to execute this command, performing system checks if needed (as
            controlled by attributes ``self.requires_system_checks`` and
            ``self.requires_model_validation``, except if force-skipped).
            """
            if options.get('no_color'):
                self.style = no_style()
                self.stderr.style_func = None
            if options.get('stdout'):
                self.stdout = OutputWrapper(options['stdout'])
            if options.get('stderr'):
                self.stderr = OutputWrapper(options.get('stderr'), self.stderr.style_func)
    
            if self.can_import_settings:
                from django.conf import settings  # NOQA
    
            saved_locale = None
            if not self.leave_locale_alone:
                # Only mess with locales if we can assume we have a working
                # settings file, because django.utils.translation requires settings
                # (The final saying about whether the i18n machinery is active will be
                # found in the value of the USE_I18N setting)
                if not self.can_import_settings:
                    raise CommandError("Incompatible values of 'leave_locale_alone' "
                                       "(%s) and 'can_import_settings' (%s) command "
                                       "options." % (self.leave_locale_alone,
                                                     self.can_import_settings))
                # Switch to US English, because django-admin creates database
                # content like permissions, and those shouldn't contain any
                # translations.
                from django.utils import translation
                saved_locale = translation.get_language()
                translation.activate('en-us')
    
            try:
                if (self.requires_system_checks and
                        not options.get('skip_validation') and  # Remove at the end of deprecation for `skip_validation`.
                        not options.get('skip_checks')):
                    self.check()
                output = self.handle(*args, **options)
                if output:
                    if self.output_transaction:
                        # This needs to be imported here, because it relies on
                        # settings.
                        from django.db import connections, DEFAULT_DB_ALIAS
                        connection = connections[options.get('database', DEFAULT_DB_ALIAS)]
                        if connection.ops.start_transaction_sql():
                            self.stdout.write(self.style.SQL_KEYWORD(connection.ops.start_transaction_sql()))
                    self.stdout.write(output)
                    if self.output_transaction:
                        self.stdout.write('
    ' + self.style.SQL_KEYWORD(connection.ops.end_transaction_sql()))         finally:             if saved_locale is not None:                 translation.activate(saved_locale)

    前処理no_color,stdout,stderrのパラメータとself.can_import_settingsプロパティ.
    そしてself.leave_locale_aloneプロパティ、translationを構成します.
    そしてパラメータskip_に従ってvalidation, skip_checksとself.requires_system_checksプロパティ、selfを呼び出す.check()エラーをチェックします.
    最後にhandle()メソッドを呼び出し、返された結果を出力します.
    コマンド全体の実行過程は上記のとおりです.
    コマンドをカスタマイズする場合は、主にクラスプロパティを設定します.
    実装add_Arguments()カスタムパラメータを追加します.
    handle()メソッドを実現し,独自の論理を実現する.
    クラスのプロパティ:
    ``args``
            A string listing the arguments accepted by the command,
            suitable for use in help messages; e.g., a command which takes
            a list of application names might set this to '<app_label
            app_label ...>'.
    
        ``can_import_settings``
            A boolean indicating whether the command needs to be able to
            import Django settings; if ``True``, ``execute()`` will verify
            that this is possible before proceeding. Default value is
            ``True``.
    
        ``help``
            A short description of the command, which will be printed in
            help messages.
    
        ``option_list``
            This is the list of ``optparse`` options which will be fed
            into the command's ``OptionParser`` for parsing arguments.
            Deprecated and will be removed in Django 2.0.
    
        ``output_transaction``
            A boolean indicating whether the command outputs SQL
            statements; if ``True``, the output will automatically be
            wrapped with ``BEGIN;`` and ``COMMIT;``. Default value is
            ``False``.
    
        ``requires_system_checks``
            A boolean; if ``True``, entire Django project will be checked for errors
            prior to executing the command. Default value is ``True``.
            To validate an individual application's models
            rather than all applications' models, call
            ``self.check(app_configs)`` from ``handle()``, where ``app_configs``
            is the list of application's configuration provided by the
            app registry.
    
        ``requires_model_validation``
            DEPRECATED - This value will only be used if requires_system_checks
            has not been provided. Defining both ``requires_system_checks`` and
            ``requires_model_validation`` will result in an error.
    
            A boolean; if ``True``, validation of installed models will be
            performed prior to executing the command. Default value is
            ``True``. To validate an individual application's models
            rather than all applications' models, call
            ``self.validate(app_config)`` from ``handle()``, where ``app_config``
            is the application's configuration provided by the app registry.
    
        ``leave_locale_alone``
            A boolean indicating whether the locale set in settings should be
            preserved during the execution of the command instead of being
            forcibly set to 'en-us'.
    
            Default value is ``False``.
    
            Make sure you know what you are doing if you decide to change the value
            of this option in your custom command if it creates database content
            that is locale-sensitive and such content shouldn't contain any
            translations (like it happens e.g. with django.contrim.auth
            permissions) as making the locale differ from the de facto default
            'en-us' might cause unintended effects.
    
            This option can't be False when the can_import_settings option is set
            to False too because attempting to set the locale needs access to
            settings. This condition will generate a CommandError.
        """

    実装add_arguments( ):
    注意argsパラメータを指定するとadd_Arguments()が追加したパラメータは役に立たない.
    handle(self,*args,*options)メソッドの実装:
    argsプロパティが設定されている場合、optionsには--version、--verbosity、--settings、--pythonpath値のいくつかのプロパティしかありません.
    argsパラメータはコマンドラインの残りのパラメータです.
    argsプロパティが指定されていない場合、argsは空のメタグループ()です.optionsはパラメータを解析した辞書です.