详解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 相关文章推荐
读写json中文ASCII乱码问题的解决方法
Nov 05 Python
python爬虫使用cookie登录详解
Dec 27 Python
Python中作用域的深入讲解
Dec 10 Python
用Python将结果保存为xlsx的方法
Jan 28 Python
Python正则表达式实现简易计算器功能示例
May 07 Python
django项目用higcharts统计最近七天文章点击量
Aug 17 Python
Python数据处理篇之Sympy系列(五)---解方程
Oct 12 Python
python TK库简单应用(实时显示子进程输出)
Oct 29 Python
python中的RSA加密与解密实例解析
Nov 18 Python
Python高阶函数、常用内置函数用法实例分析
Dec 26 Python
Django模板获取field的verbose_name实例
May 19 Python
手把手教你用Django执行原生SQL的方法
Feb 18 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
用php或asp创建网页桌面快捷方式的代码
2010/03/23 PHP
PHP仿盗链代码
2012/06/03 PHP
Cygwin中安装PHP方法步骤
2015/07/04 PHP
兼容多浏览器的iframe自适应高度(ie8 、谷歌浏览器4.0和 firefox3.5.3)
2009/11/04 Javascript
JS 自定义函数缺省值的设置方法
2010/05/05 Javascript
javascript获取隐藏dom的宽高 具体实现
2013/07/14 Javascript
$.each遍历对象、数组的属性值并进行处理
2014/07/18 Javascript
jQuery不使用插件及swf实现无刷新文件上传
2014/12/08 Javascript
JS使用正则表达式除去字符串中重复字符的方法
2015/11/05 Javascript
JS实现的仿淘宝交易倒计时效果
2015/11/27 Javascript
原生js编写autoComplete插件
2016/04/13 Javascript
JS中用EL表达式获取上下文参数值的方法
2018/03/28 Javascript
vue项目刷新当前页面的三种方法
2018/12/04 Javascript
微信小程序前端promise封装代码实例
2019/08/24 Javascript
js实现表格单列按字母排序
2020/08/12 Javascript
Postman环境变量全局变量使用方法详解
2020/08/13 Javascript
[56:56]VG vs LGD 2019国际邀请赛淘汰赛 胜者组 BO3 第一场 8.22
2019/09/05 DOTA
初步探究Python程序的执行原理
2015/04/11 Python
Python 记录日志的灵活性和可配置性介绍
2018/02/27 Python
wxPython实现窗口用图片做背景
2018/04/25 Python
解决Python找不到ssl模块问题 No module named _ssl的方法
2019/04/29 Python
Python3enumrate和range对比及示例详解
2019/07/13 Python
DjangoWeb使用Datatable进行后端分页的实现
2020/05/18 Python
如何基于python把文字图片写入word文档
2020/07/31 Python
python之pygame模块实现飞机大战完整代码
2020/11/29 Python
HTML5 Convas APIs方法详解
2015/04/24 HTML / CSS
宝拉珍选英国官网:Paula’s Choice英国
2019/05/29 全球购物
人力资源管理专业应届生求职信
2014/04/24 职场文书
学生会竞选演讲稿学习部
2014/08/25 职场文书
2014年学校工作总结
2014/11/20 职场文书
宾馆卫生管理制度
2015/08/06 职场文书
关于运动会的广播稿
2015/08/19 职场文书
2016年全国爱牙日宣传活动总结
2016/04/05 职场文书
解析高可用Redis服务架构分析与搭建方案
2021/06/20 Redis
继承Win10缺点!教你关闭Win11烦人的网络搜索
2021/11/23 数码科技
DE1103使用报告
2022/04/05 无线电