Django源码分析1:创建项目和应用分析

本文详细解析了Django命令行工具的工作原理,介绍了其核心组件django-admin.py的主要功能及内部实现流程,对于理解Django项目的启动过程有重要作用。

转载地址:http://blog.youkuaiyun.com/qq_33339479/article/details/78862156

django命令行源码分析

本文环境python3.5.2,django1.10.x系列

当命令行输入时django-admin时:

(venv) ACA80166:dbManger wuzi$ django-admin

Type 'django-admin help <subcommand>' for help on a specific subcommand.

Available subcommands:

[django]
    check
    compilemessages
    createcachetable
    dbshell
    diffsettings
    dumpdata
    flush
    inspectdb
    loaddata
    makemessages
    makemigrations
    migrate
    runserver
    sendtestemail
    shell
    showmigrations
    sqlflush
    sqlmigrate
    sqlsequencereset
    squashmigrations
    startapp
    startproject
    test
    testserver
Note that only Django core commands are listed as settings are not properly configured (error: Requested setting INSTALLED_APPS, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.).

此时,支持的命令只有24个命令,该命令都是由django默认提供支持的命令,并且这些命令对应的具体执行文件都是位于django/core/management/commands/中,并且都是通过django/bin/django-admin.py文件执行来调用,由此先看下django-admin的具体代码分析:

#!/usr/bin/env python
from django.core import management

if __name__ == "__main__":
    management.execute_from_command_line()

调用management包的init.py文件中的execute_from_command_line函数:

def execute_from_command_line(argv=None):
    """
    A simple method that runs a ManagementUtility.
    """
    utility = ManagementUtility(argv)
    utility.execute()

在实例化对象后调用了utility.execute()方法

def execute(self):
    """
    Given the command-line arguments, this figures out which subcommand is
    being run, creates a parser appropriate to that command, and runs it.
    """
    try:
        subcommand = self.argv[1]  # 获取命令行输入第一个参数,如果没有则为help
    except IndexError:
        subcommand = 'help'  # Display help if no arguments were given.

    # Preprocess options to extract --settings and --pythonpath.
    # These options could affect the commands that are available, so they
    # must be processed early.
    parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False)  # 添加命令说明
    parser.add_argument('--settings')
    parser.add_argument('--pythonpath')
    parser.add_argument('args', nargs='*')  # catch-all
    try:
        options, args = parser.parse_known_args(self.argv[2:])  # 解析后面的参数,options:Namespace(args=[],pythonpath=None,settings=None)
        handle_default_options(options)  # 如果options中的pythonpath或者settings有,则使用传入的路径与文件
    except CommandError:
        pass  # Ignore any option errors at this point.

    no_settings_commands = [
        'help', 'version', '--help', '--version', '-h',
        'compilemessages', 'makemessages',
        'startapp', 'startproject',
    ]

    try:
        settings.INSTALLED_APPS  # 当是django-admin输入时没有配置文件此时会报错,如果是已经生产的项目则可以导入配置文件中已经配置的应用
    except ImproperlyConfigured as exc:
        self.settings_exception = exc
        # A handful of built-in management commands work without settings.
        # Load the default settings -- where INSTALLED_APPS is empty.
        if subcommand in no_settings_commands:
            settings.configure()  # 使用django默认提供的全局默认的配置文件

    if settings.configured:
        # Start the auto-reloading dev server even if the code is broken.
        # The hardcoded condition is a code smell but we can't rely on a
        # flag on the command class because we haven't located it yet.
        if subcommand == 'runserver' and '--noreload' not in self.argv:  # 如果不是runserver并且没有关闭自动重载功能,则执行以下函数
            try:
                autoreload.check_errors(django.setup)()  # 调用自动检测文件是否修改如果修改则自动重新启动Django服务
            except Exception:
                # The exception will be raised later in the child process
                # started by the autoreloader. Pretend it didn't happen by
                # loading an empty list of applications.
                apps.all_models = defaultdict(OrderedDict)
                apps.app_configs = OrderedDict()
                apps.apps_ready = apps.models_ready = apps.ready = True

        # In all other cases, django.setup() is required to succeed.
        else:
            django.setup()  # 初始化django环境

    self.autocomplete()  # 检测是否是自动完成

    if subcommand == 'help':  # 如果解析命令为help
        if '--commands' in args:
            sys.stdout.write(self.main_help_text(commands_only=True) + '\n')  # 打印出help命令
        elif len(options.args) < 1:  # 如果输入参数为空
            sys.stdout.write(self.main_help_text() + '\n')
        else:
            self.fetch_command(options.args[0]).print_help(self.prog_name, options.args[0])  # 针对某个命令打印相应命令的帮助信息
    # Special-cases: We want 'django-admin --version' and
    # 'django-admin --help' to work, for backwards compatibility.
    elif subcommand == 'version' or self.argv[1:] == ['--version']:  # 如果输入的命令是打印版本信息
        sys.stdout.write(django.get_version() + '\n')  # 则输出当前Django的版本
    elif self.argv[1:] in (['--help'], ['-h']):  # 如果输入参数中包括了--help -h 则打印帮助信息
        sys.stdout.write(self.main_help_text() + '\n')
    else:
        self.fetch_command(subcommand).run_from_argv(self.argv)  # 如果命令行输入单个命令,则寻找该命令,然后执行输入的参数

转载于:https://www.cnblogs.com/yuanoung/p/8435868.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值