Django命令模块

这篇具有很好参考价值的文章主要介绍了Django命令模块。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这篇文章我们主要来介绍一下关于 Django 的命令模块,我们经常会使用到,比如以下几个常用的命令,都属于 Django 的命令模块:

python manage.py makemigrations
python manage.py migrate
python manage.py startapp
python manage.py runserver

management 模块是 Django 框架中用于管理命令行操作的核心组件。它提供了一种简单而强大的方式,让开发人员可以通过命令行执行各种任务,如数据库迁移、创建超级用户、运行开发服务器等。

目录结构

本质上,在 Django 中,这些都是使用 management 模块来进行管理的,我们可以在 Django 源码目录以及通过 python manage.py startapp 创建的 app 目录中查看到所有支持的命令,在 Django 源码中,主要位于以下路径:django.core.management,目录结构如下:

├── management
│   ├── __init__.py
│   ├── __pycache__
│   ├── base.py
│   ├── color.py
│   ├── commands
│   ├── sql.py
│   ├── templates.py
│   └── utils.py

核心的内容都位于 commands 目录下,我们再来看一下 commands 目录下都有什么文件:

├── commands
│   ├── __init__.py
│   ├── __pycache__
│   ├── 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

是不是非常熟悉,我们平常执行 python manage.py help 所展示的命令,几乎都位于这里。

对于 Django 来说,它定义了关于命令模块的一些规则,我们只需要遵循即可找到相关的内置命令及实现自己的命令,后面会通过查看源码来解析原因:

  • management和commands每个目录下都必须有个__init__.py空文件,表明这是一个python包。另外以下划线开头的文件名不能用作管理命令脚本。
  • management/commands目录可以位于任何一个app的目录下,Django都能找到它。
  • 一般建议每个python脚本文件对应一条管理命令。

Django是如何定义命令的

management 模块的实现涉及多个关键类和函数,我们来深入了解其中的一些重要概念和源码。

Django启动入口文件

我们从最熟悉的 Django 启动方式开始。我们都知道启动 Django的方式:python manage.py runserver,查看 manage.py 文件的核心部分:

    from django.core.management import execute_from_command_line

    execute_from_command_line(sys.argv)

发现其调用了management 模块的 execute_from_command_line:

def execute_from_command_line(argv=None):
    """Run a ManagementUtility."""
    utility = ManagementUtility(argv)
    utility.execute()

我们从 ManagementUtility 这个核心类开始入手解析我们的命令模块。

ManagementUtility类

ManagementUtility 类是 Django management 模块中的核心类,它位于 django.core.management 包中。这个类负责解析命令行参数,并根据参数执行相应的命令。

简化后的 ManagementUtility 的核心代码如下,并对重要的部分做了注释:

class ManagementUtility:

    def __init__(self, argv=None):
        # 初始化操作
        pass

    def main_help_text(self, commands_only=False):
        # 打印帮助文档
        pass

    def fetch_command(self, subcommand):
        # 根据传入的子命令名称 subcommand 返回该命令的类
        commands = get_commands()
        try:
            app_name = commands[subcommand]
        except KeyError:
            # 主要处理当输入命令错误或不存在时的错误信息
            pass
        if isinstance(app_name, BaseCommand):
            klass = app_name
        else:
            klass = load_command_class(app_name, subcommand)
        return klass

    def autocomplete(self):
        # 用于自动补全命令的。它是一个便利方法,可以帮助开发人员在命令行中输入管理命令时提供自动补全的功能。
        pass

    # 核心方法,整个命令入口执行的关键
    def execute(self):
        # 当不传任何命令是,默认执行 help 命令,即执行 python manage.py 等同于 python manage.py help
        try:
            subcommand = self.argv[1]
        except IndexError:
            subcommand = "help"  # Display help if no arguments were given.

        # 解析传入的命令行参数
        parser = CommandParser(
            prog=self.prog_name,
            usage="%(prog)s subcommand [options] [args]",
            add_help=False,
            allow_abbrev=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:])
            handle_default_options(options)
        except CommandError:
            pass  # Ignore any option errors at this point.

        # 确保所有的 INSTALLED_APPS 已经正确加载
        try:
            settings.INSTALLED_APPS
        except ImproperlyConfigured as exc:
            self.settings_exception = exc
        except ImportError as exc:
            self.settings_exception = exc
        
        if settings.configured:
            # 当命令为runserver并且不是 --noreload 模式时执行
            if subcommand == "runserver" and "--noreload" not in self.argv:
                try:
                    autoreload.check_errors(django.setup)()
                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(dict)
                    apps.app_configs = {}
                    apps.apps_ready = apps.models_ready = apps.ready = True

                    # Remove options not compatible with the built-in runserver
                    # (e.g. options for the contrib.staticfiles' runserver).
                    # Changes here require manually testing as described in
                    # #27522.
                    _parser = self.fetch_command("runserver").create_parser(
                        "django", "runserver"
                    )
                    _options, _args = _parser.parse_known_args(self.argv[2:])
                    for _arg in _args:
                        self.argv.remove(_arg)

            # 进行 django 初始化操作,这也是 django 启动必须执行的第一个初始化动作
            else:
                django.setup()
        
        # 自动补全命令
        self.autocomplete()

        if subcommand == "help":
            # 打印帮助信息
            pass
        elif subcommand == "version" or self.argv[1:] == ["--version"]:
            # 打印 django 版本信息
            sys.stdout.write(django.get_version() + "\n")
        elif self.argv[1:] in (["--help"], ["-h"]):
            # 同样是打印帮助信息
            sys.stdout.write(self.main_help_text() + "\n")
        else:
            # 执行具体子命令的 run_from_argv 方法,子命令为继承了 BaseCommand 类的子类
            self.fetch_command(subcommand).run_from_argv(self.argv)

ManagementUtility类中最重要的就是 execute 方法,主要包括了以下几步:

  1. 检查传入的参数:根据传入的参数判断执行何种子命令。
  2. 通过 CommandParser 对象来解析命令行参数,并调用 parse_known_args() 方法解析参数
  3. django 初始化: django.setup 确保 django 初始化。
  4. 调用子命令:根据子命令获取相应的命令类,并创建该命令类的实例,执行该命令实例的 run_from_argv 方法执行具体的命令内容。

通过上面的步骤,我们发现最后会执行具体子命令的 run_from_argv 方法,子命令为继承了 BaseCommand 类的子类,接下来我们来看看 BaseCommand 类。

BaseCommand类

每一个自定义的管理命令本质是一个Command类, 它继承了Django的Basecommand或其子类, 主要通过重写handle()方法实现自己的业务逻辑代码,而add_arguments()则用于帮助处理命令行的参数,如果运行命令时不需要额外参数,可以不写这个方法,下面是 BaseCommand 类的主要代码:

class BaseCommand:
     # 帮助文本, 一般备注命令的用途及如何使用。
     help = 'Some help texts'

    def add_arguments(self, parser):
        # 当我们自定义的命令类需要添加额外的参数选项时,重写这个方法
        pass

    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 执行子命令的逻辑
            self.execute(*args, **cmd_options)
        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

    def execute(self, *args, **options):
        """
        Try to execute this command, performing system checks if needed (as
        controlled by the ``requires_system_checks`` attribute, except if
        force-skipped).
        """
        if options["force_color"] and options["no_color"]:
            raise CommandError(
                "The --no-color and --force-color options can't be used together."
            )
        if options["force_color"]:
            self.style = color_style(force_color=True)
        elif options["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["stderr"])

        if self.requires_system_checks and not options["skip_checks"]:
            if self.requires_system_checks == ALL_CHECKS:
                self.check()
            else:
                self.check(tags=self.requires_system_checks)
        if self.requires_migrations_checks:
            self.check_migrations()
        output = self.handle(*args, **options)
        if output:
            if self.output_transaction:
                connection = connections[options.get("database", DEFAULT_DB_ALIAS)]
                output = "%s\n%s\n%s" % (
                    self.style.SQL_KEYWORD(connection.ops.start_transaction_sql()),
                    output,
                    self.style.SQL_KEYWORD(connection.ops.end_transaction_sql()),
                )
            self.stdout.write(output)
        return output

    def handle(self, *args, **options):
        # 任何自定义的命令都需要实现 handle 方法,这里是具体的子命令执行逻辑
        raise NotImplementedError(
            "subclasses of BaseCommand must provide a handle() method"
        )

BaseCommand类中最重要的就是如下几个方法:

  1. add_arguments:这个方法用于添加自定义的命令行参数。
  2. handle: 这是 BaseCommand 类中最重要的方法,用于执行实际的命令逻辑。当管理命令被调用时,Django 将调用该方法。你需要在子类中重写这个方法,并在其中定义你的命令的具体逻辑。
  3. run_from_argv(argv): 这个方法用于从命令行参数列表 argv 中解析命令并执行它。它是 BaseCommand 类的入口点方法,被 Django 的管理脚本 manage.py 调用。它会解析命令行参数,调用 handle() 方法执行实际的命令逻辑。
  4. execute :用于执行实际的命令逻辑的核心方法,execute 方法会调用 handle 方法,处理解析参数,在执行 handle 方法时,如果发生错误,execute 方法会捕获并处理这些错误。

自定义命令

要注册自定义命令,我们需要在 Django 项目的某个应用中创建一个名为 management 的子目录,并在该目录中创建一个名为 commands 的子目录。在 commands 目录中,我们可以创建一个 Python 模块文件,并定义一个继承自 BaseCommand 的命令类。

以下是一个简单的自定义命令的示例:

from django.core.management.base import BaseCommand

class Command(BaseCommand):
    help = 'This is my custom command.'

    def handle(self, *args, **options):
        self.stdout.write('Hello from my custom command!')

在上述示例中,我们创建了一个名为 Command 的自定义命令类,从Django4开始,该类的名称必须为Command,继承自 BaseCommand。在 handle() 方法中,我们简单地输出了一条消息。

要执行自定义命令,我们可以在命令行中使用以下命令:

python manage.py hello_world

其中,hello_world 是我们自定义命令的名称。文章来源地址https://www.toymoban.com/news/detail-793265.html

到了这里,关于Django命令模块的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Django的contrib模块介绍

    在Django中, contrib 是一个缩写,代表了\\\"contribution\\\"(贡献)一词。 contrib 模块是Django框架提供的一组官方贡献模块的集合,它们为开发者提供了各种可重用的功能和组件,以便快速构建Web应用程序。 contrib 模块通常包含与常见应用程序需求相关的功能,例如身份验证、会话管

    2024年02月13日
    浏览(48)
  • Django入门学习-了解基本模块

    目录 MVT设计了解 认识MVT 实际操作 Template: View: 路由配置 Model: 默认的后台管理模块 初始化admin模块 应用中Admin注册 Django的web设计模型是MVT: Model:数据存储层,处理所有数据相关的业务,和数据库进行交互,并提供数据的增删改查; Template:模板层(也叫表现层)具体来处

    2023年04月11日
    浏览(32)
  • Django——Auth模块以及admin站点

    Auth 用户认证,本质上也是设置 Session。 在 django 迁移数据库的是时候会自动生成一个用户认证表:auth_user , 存放用户基本信息(用户名 , 密码,邮箱……) 重新配置 auth 认证模型类 实现验证登录,以及退出登录 django 提供的网站后台数据管理 创建管理员用户 注册的时候,

    2024年04月29日
    浏览(37)
  • 43.Django权限系统auth模块详解

    昨天我们为了登录admin,通过命令创建了超级用户,你是不是有个疑问——这创建的超级用户的信息是存放在哪里了呢?   这就想到了我们映射数据库时,Django自动创建的一些表(这也是之前进行数据库迁移时没有提到的那些表)!!!   如上图就是Django自带的auth系统对

    2023年04月08日
    浏览(36)
  • windows解决python安装django架构没有django-admin命令

    目录 一.尝试安装与配置 1.直接pip命令安装 2.用pycharm测试 3.官网下包安装 二.解决 1.找到django安装的路径 2.配置系统变量 3.测试创建项目 3.1.执行访问页面 3.2.解决 3.3.继续测试 4.pycharm打开     新建项目测试    注:发现没有django这个框架选项,后面发现这个功能只有专业版才

    2024年02月06日
    浏览(55)
  • Django 用相对路径方式引用自定义模块 或 文件

    Django的文件夹结构 projectName/websiteName/appName manage.py 所在路径为:D:/projectA/website1/manage.py views.py 所在路径为:D:/projectA/website1/app1/views.py D:/projectA/website1/app1/module1.py 如果要引用自定义模块,引用自定义的模块  from .A import AAA    (在 if __name__ == \\\"__main__\\\" 中会报错) from A import

    2024年02月09日
    浏览(45)
  • Django-------自定义命令

    每次在启动Django服务之前,我们都会在终端运行python manage.py xxx的管理命令。其实我们还可以自定义管理命令,这对于执行独立的脚本或任务非常有用,比如清除缓存、导出用户邮件清单或发送邮件等等。 自定义的管理命令不仅可以通过manage.py运行,还可以通过Linux或Celer

    2024年02月14日
    浏览(28)
  • redis(其它操作、管道)、django中使用redis(通用方案、 第三方模块)、django缓存、celery介绍(celery的快速使用)

    1 redis其它操作 2 redis管道 3 django中使用redis 3.1 通用方案 3.2 第三方模块 4 django缓存 5 celery介绍 5.1 celery的快速使用

    2024年02月07日
    浏览(50)
  • Django框架:入门指南与常用命令

    引言: 在当今的Web开发世界中,Django无疑是一个备受瞩目的框架。它以其强大的功能和易用性,吸引着越来越多的开发者。这篇博客将为你提供一个关于Django的概览,以及一些常用的命令,帮助你快速上手。 一、Django简介: Django是一个高级Python Web框架,它鼓励快速开发和干

    2024年02月03日
    浏览(43)
  • 【Python-Django】如何在一个项目中创建多个app模块

    django开发案例:a​​​​​【Django】开发日报_1_Day:用户管理系统案例-创建项目_django 开发用户管理系统_代码骑士的博客-CSDN博客 前面做过的管理系统项目功能比较单一,只用一个模块就能解决问题。如果想创建多个不同的模块的话,就需要创建多个app组件,下面就介绍一

    2024年02月06日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包