Core.Management 模块
Management 模块是 Django 的核心模块之一,它承担了 Django 脚手架命令。
通过学习该模块,可以指导自己如何设计脚手架,以及了解脚手架需要哪些功能。
模块结构
.
├── __init__.py
├── base.py # 脚手架基类
├── color.py
├── commands # 脚手架命令目录 文件名即为命令名
│ ├── __init__.py
│ ├── check.py
│ ├── compilemessages.py
│ ├── createcachetable.py
│ ├── dbshell.py
│ ├── diffsettings.py
│ ├── dumpdata.py
│ ├── flush.py
│ ├── inspectdb.py
│ ├── loaddata.py
│ ├── makemessages.py
│ ├── makemigrations.py
│ ├── migrate.py
│ ├── optimizemigration.py
│ ├── runserver.py
│ ├── sendtestemail.py
│ ├── shell.py
│ ├── showmigrations.py
│ ├── sqlflush.py
│ ├── sqlmigrate.py
│ ├── sqlsequencereset.py
│ ├── squashmigrations.py
│ ├── startapp.py
│ ├── startproject.py
│ ├── test.py
│ └── testserver.py
├── sql.py
├── templates.py # 脚手架模板命令,生成项目模板或app模板
└── utils.py
2 directories, 32 files
脚手架执行流程
源码分析
脚手架基类
base.py
文件定义了 BaseCommand
类,该类是所有脚手架命令的基类。
- 子类实现
add_arguments
方法,可以自定义命令行参数 - 子类实现
handle
方法,自定义执行命令的主要逻辑
class BaseCommand:
...
def add_arguments(self, parser):
"""
Entry point for subclassed commands to add custom arguments.
"""
// 子类实现,自定义命令行参数
def handle(self, *args, **options):
"""
The actual logic of the command. Subclasses must implement this method.
"""
// 子类实现,自定义执行命令的主要逻辑
Command
命令入口run_from_argv
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])
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", ())
handle_default_options(options)
try:
self.execute(*args, **cmd_options) # 调用`execute`方法
except CommandError as e:
if options.traceback:
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(e.returncode)
finally:
try:
connections.close_all()
except ImproperlyConfigured:
# Ignore if connections aren't setup at this point (e.g. no
# configured settings).
pass
AppCommand
默认加入了app_label
位置参数,允许多个 app_label 传入,并将其传递给handle_app_config
方法。
继承此类来快速实现对 app 的命令。
规定了必须实现handle_app_config
def handle_app_config(self, app_config, **options):
"""
Perform the command's actions for app_config, an AppConfig instance
corresponding to an application label given on the command line.
"""
raise NotImplementedError('subclasses of AppCommand must provide a handle_app_config() method')
LabelCommand
默认加入label
位置参数,允许多个 label 传入,并将其传递给handle_label
方法。
继承此类来快速实现对 label 的命令。
规定了必须实现handle_label
def handle_label(self, label, **options):
"""
Perform the command's actions for label, a string representing an
application label given on the command line.
"""
raise NotImplementedError('subclasses of LabelCommand must provide a handle_label() method')