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


Posted in Python onAugust 13, 2019

在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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python程序设计入门(3)数组的使用
Jun 16 Python
Python实现二维有序数组查找的方法
Apr 27 Python
ubuntu17.4下为python和python3装上pip的方法
Jun 12 Python
Python中如何使用if语句处理列表实例代码
Feb 24 Python
python 调用pyautogui 实时获取鼠标的位置、移动鼠标的方法
Aug 27 Python
解决pytorch-yolov3 train 报错的问题
Feb 18 Python
python GUI框架pyqt5 对图片进行流式布局的方法(瀑布流flowlayout)
Mar 12 Python
Django多层嵌套ManyToMany字段ORM操作详解
May 19 Python
Java多线程实现四种方式原理详解
Jun 02 Python
Python日志打印里logging.getLogger源码分析详解
Jan 17 Python
selenium+python自动化78-autoit参数化与批量上传功能的实现
Mar 04 Python
Python字符串的转义字符
Apr 07 Python
Python一键安装全部依赖包的方法
Aug 12 #Python
Python之time模块的时间戳,时间字符串格式化与转换方法(13位时间戳)
Aug 12 #Python
浅谈Python2之汉字编码为unicode的问题(即类似\xc3\xa4)
Aug 12 #Python
基于Python2、Python3中reload()的不同用法介绍
Aug 12 #Python
Python递归函数 二分查找算法实现解析
Aug 12 #Python
基于Python安装pyecharts所遇的问题及解决方法
Aug 12 #Python
Django实现发送邮件找回密码功能
Aug 12 #Python
You might like
使用JSON实现数据的跨域传输的php代码
2011/12/20 PHP
thinkPHP商城公告功能开发问题分析
2016/12/01 PHP
php-fpm超时时间设置request_terminate_timeout资源问题分析
2019/09/27 PHP
在laravel-admin中列表中禁止某行编辑、删除的方法
2019/10/03 PHP
jQuery each()方法的使用方法
2010/03/18 Javascript
一个级联菜单代码学习及removeClass与addClass的应用
2013/01/24 Javascript
checkbox设置复选框的只读效果不让用户勾选
2013/08/12 Javascript
js实现div层缓慢收缩与展开的方法
2015/05/11 Javascript
基于javascript实现tab切换特效
2016/03/29 Javascript
HTML5+jQuery插件Quicksand实现超酷的星际争霸2兵种分类展示效果(附demo源码下载)
2016/05/25 Javascript
js实现千分符和保留几位小数的简单实例
2016/08/01 Javascript
jQ处理xml文件和xml字符串的方法(详解)
2016/11/22 Javascript
微信公众平台开发教程(四) 实例入门:机器人回复(附源码)
2016/12/02 Javascript
关于vue.js v-bind 的一些理解和思考
2017/06/06 Javascript
vue项目中v-model父子组件通信的实现详解
2017/12/10 Javascript
JS/HTML5游戏常用算法之碰撞检测 地图格子算法实例详解
2018/12/12 Javascript
JavaScript布尔运算符原理使用解析
2020/05/06 Javascript
Element Input输入框的使用方法
2020/07/26 Javascript
vue插件--仿微信小程序showModel实现模态提示窗功能
2020/08/19 Javascript
Python下的subprocess模块的入门指引
2015/04/16 Python
轻松实现python搭建微信公众平台
2016/02/16 Python
python模块之time模块(实例讲解)
2017/09/13 Python
python 寻找优化使成本函数最小的最优解的方法
2017/12/28 Python
啥是佩奇?使用Python自动绘画小猪佩奇的代码实例
2019/02/20 Python
详解Python函数式编程—高阶函数
2019/03/29 Python
Python基础学习之时间转换函数用法详解
2019/06/18 Python
python如何从键盘获取输入实例
2020/06/18 Python
加拿大女包品牌:Matt & Nat
2017/05/12 全球购物
医药个人求职信范文
2014/01/29 职场文书
关于孝道的演讲稿
2014/05/21 职场文书
小学领导班子对照材料
2014/08/23 职场文书
2014年学校国庆主题活动方案
2014/09/16 职场文书
旷课检讨书
2015/01/26 职场文书
2015年教师工作总结范文
2015/03/31 职场文书
2015年第十五个全民国防教育日宣传活动方案
2015/05/06 职场文书
不要在HTML中滥用div
2021/05/08 HTML / CSS