• django实现自定义manage命令的扩展


    在Django开发过程中我们都用过django-admin.py和manage.py命令。

    django-admin.py是一个命令行工具,可以执行一些管理任务,比如创建Django项目。而manage.py是在创建每个Django project时自动添加在项目目录下的,只是对manage.py的一个简单包装,其功能是将Django project放到sys.path目录中,同时设置DJANGO_SETTINGS_MODULE环境变量为当前project的setting.py文件。

    Django 对于命令的添加有自己的一套规范,我们可以为每个app 指定命令。简单来书就是我们在使用manage.py文件执行命令的时候,可以自定制自己的命令,来实现命令的扩充。

    对于自定义Command我们从两方面介绍一是内部执行原理,二是如何实行自定义Command

    一、内部原理实现

    django-admin.py调用django.core.management来执行命令:

    创建django项目会自动生成manage.py文件:

    import os
    import sys
    
    
    def main():
        os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'gaoyou.settings')
        try:
            from django.core.management import execute_from_command_line
        except ImportError as exc:
            raise ImportError(
                "Couldn't import Django. Are you sure it's installed and "
                "available on your PYTHONPATH environment variable? Did you "
                "forget to activate a virtual environment?"
            ) from exc
        execute_from_command_line(sys.argv)
    
    
    if __name__ == '__main__':
        main()

    excute_from_command_line()函数会根据命令行参数解析出命令的名称,根据命令名称调用相应的Command执行命令。Command位于各个管理模块的commands模块下面。

    commands的创建方法:

    1、在app内创建一个名字为:management文件夹(在你自己指定的应用下创建即可)
    2、在management文件夹里面创建名为:commands的文件夹
    3、在commands文件夹下创建名为:任意py文件(启动的时候就是根据该文件名进行启动的,注意:commands目录内都包含__init__.py文件)

    此时py文件名就是你的自定制命令,我们可以使用下面方式进行执行

    python manage.py 命令名(即任意py文件名不用加.py)
    #类似我们迁移数据库命令
    #python manage.py makemigrations
    #python manage.py migrate

    所谓管理模块,是指在app模块下的名字为management的模块。Django通过django.core.management.find_management_module函数发现"管理模块":

    django.core.management.find_management_module()
    def find_management_module(app_name):
        """
        Determines the path to the management module for the given app_name,
        without actually importing the application or the management module.
    
        Raises ImportError if the management module cannot be found for any reason.
        """
        parts = app_name.split('.')
        parts.append('management')
        parts.reverse()
        part = parts.pop()
        path = None

    然后通过django.core.management.find_commands函数找到命令类。find_commands函数会在管理模块下查找.py文件,并将.py文件的名称匹配到命令名称:

    def find_commands(management_dir):
        """
        Given a path to a management directory, returns a list of all the command
        names that are available.
    
        Returns an empty list if no commands are defined.
        """
        command_dir = os.path.join(management_dir, 'commands')
        try:
            return [f[:-3] for f in os.listdir(command_dir)
               if not f.startswith('_') and f.endswith('.py')]
        except OSError:
        return []

    最后,通过django.core.management.load_command_class函数加载该.py文件中的Command类:

    def load_command_class(app_name, name):
        """
        Given a command name and an application name, returns the Command
        class instance. All errors raised by the import process
        (ImportError, AttributeError) are allowed to propagate.
        """
        module = import_module('%s.management.commands.%s' % (app_name, name))
        return module.Command()

    在执行命令的时候,会执行相应Command类的handle方法。所有的Command类都应该是django.core.management.base.BaseCommand的直接或间接子类。

    二、自定义应用

    Django的Command命令是要放到我们创建app下的management/commands目录下的(需自己手动创建该文件目录)。

    注意:请确保management/commands目录下包含__init__.py文件

    首先对于文件名可以自行定义没有要求,内部需要定义一个Command类并继承BaseCommand类或其子类。

    1. 它必须定义一个Command类并扩展自BaseCommand或其 子类。
    2. 其中help是command功能作用简介,handle函数是主处理程序,add_arguments函数是用来接收可选参数的(如果没有参数该方法可以不写)

    我们通过在输入命令后再控制台输出一个hello world为例:

    task.py

    from django.core.management.base import BaseCommand, CommandError
    from django.db import models
    
    class Command(BaseCommand):
        help = '每日凌晨对当天数据库进行更新'
    
        def handle(self, *args, **options):
            print('hello world')

    在Terminal控制台将目录切换到你创建的Django项目目录下执行:python manage.py task

    执行后即可在控制台看到输出hello world 说明自定义Commond成功!!!

    如果在输入命令想要输出参数怎么办呢?例如:python mange.py task 参数

    task.py

    from django.core.management.base import BaseCommand, CommandError
    from django.db import models
    
    
    class Command(BaseCommand):
        help = '每日凌晨对当天数据库进行更新'
    
        # 接收参数
        def add_arguments(self, parser):
            parser.add_argument('offset', type=int, help='天数转移量')
    
        def handle(self, *args, **options):
            offset = options['offset']  # 拿到参数的值
            print(offset)
            print('hello world')
            self.stdout.write(self.style.SUCCESS('{} Successfully {}'.format('接收成功', offset)))  #可以自定制在控制台输出的内容

    在Terminal控制台将目录切换到你创建的Django项目目录下执行:python manage.py task  1314

    自定义django-admin命令可以用来设置一些定时脚本,让其在指定的时间内进行运行

     

  • 相关阅读:
    2020去奔跑
    2020前两个月学习心得
    2020年1_2月寒假学习心得
    寒假中期考核个人总结
    Numpy、Matplotlib和pandas学习路线引导
    Python学习路线引导-Python入门基础
    2019在路上
    2020/11/28助教一周小结(第九周)
    2020/11/3助教一周小结(第五周)
    2020/10/25助教一周小结(第四周)
  • 原文地址:https://www.cnblogs.com/sui776265233/p/11341120.html
Copyright © 2020-2023  润新知