django.core.management.init.py
-
將 execute_from_command_line 方法對外暴露,也就是django manage.py 中的標準引用
def execute_from_command_line(argv=None): utility = ManagementUtility(argv) utility.execute() -
ManagementUtility 寫法
class ManagementUtility(object): def __init__(self, argv=None): self.argv = argv or sys.argv[:] self.prog_name = os.path.basename(self.argv[0]) self.settings_exception = None def execute(self): parser = LaxOptionParser(...) options, args = parser.parse_args(self.argv) handle_default_options(options) .... self.fetch_command(subcommand).run_from_argv(self.argv) def fetch_command(self, subcommand): #getCommands()會把django.core.management.commands中的 #所有文件一一列出來,因為一個文件就是對應一個命令 commands = get_commands() app_name = commands[subcommand] if isinstance(app_name, BaseCommand): klass = app_name else: klass = load_command_class(app_name, subcommand)
所有的Command繼承于BaseCommand,run_from_argv方法是BaseCommand定義的方法。這樣,就把所有的命令通過這里分發(fā)到不同的Command中去執(zhí)行了。
-
下面是BaseCommand類的方法定義
class BaseCommand(object): def create_parser(self, prog_name, subcommand): return OptionParser(prog=prog_name, usage=self.usage(subcommand), version=self.get_version(), option_list=self.option_list) def run_from_argv(self, argv): parser = self.create_parser(argv[0], argv[1]) options, args = parser.parse_args(argv[2:]) handle_default_options(options) self.execute(*args, **options.__dict__) def execute(self, *args, **options): self.stdout = OutputWrapper(options.get('stdout', sys.stdout)) self.check() output = self.handle(*args, **options) self.stdout.write(output) def check(self, app_configs=None, tags=None, display_num_errors=False): all_issues = checks.run_checks(app_configs=app_configs, tags=tags) def handle(self, *args, **options): raise NotImplementedError('subclasses of BaseCommand must provide a handle() method')
子Command類需要做的是,重寫handle方法。
對于BaseCommand來說,有幾個重要的事情
- 解析命令行的參數(shù) create_parser, 使用python的內(nèi)置OptionParser來解析參數(shù)
- 校驗參數(shù) check, 實際使用checks.run_checks方法。 具體分析看 Django源碼分析-checks設(shè)計
- 執(zhí)行 實際調(diào)用handle方法執(zhí)行實際邏輯