IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 自定义Django-admin管理命令 -> 正文阅读

[Python知识库]自定义Django-admin管理命令

django本身是有一些django-admin命令的,他们都是基于manage.py来使用的。

比如,python3 manage.py?createsuperuser xxx

? ? ? ? ? ?python3 manage.py makemigrations

? ? ? ? ? ?python3 manage.py migrate

? ? ? ? ? ?python3 manage.py dumpdata path.modle --pk num? # 将数据库中表名为modle,pk为 unm的数据导出来

? ? ? ? ? ?python3 manage.py loaddata xxx.json? ?# 将有表数据的json文件导入数据库

等等...

但是,更多时候,我们对于工程的操作,往往是需要自己定义一些命令的,以更方便的操控工程。所以,就有了自定义 django-admin 管理命令一说。

举个简单的例子,fab 是可以用作在远程机器上执行命令的一个工具,有时候,我们会将部署服务的命令集成到 fabfile.py,这样,就可以使用 fab 命令去完成服务的部署了。但是 fab 往往是单独存在的,需要我们在terminal直接输入 fab 命令,这样跟整个工程的粘度,就不是很大了。所以我们会考虑将 fab 集成到 django-admin 里, 通过 python3 manage.py fab task:param?remote_machine_address,的这类命令,直接实现服务的部署操作。

对于自定义的 django-admin 的创建,本身并不难:

首先:自定义的Django-admin管理命令本质上是一个python脚本文件,它的存放路径必须遵循一定的规范,一般位于app/management/commands目录。整个文件夹的布局如下所示:

app01/
    __init__.py
    models.py
    management/
        __init__.py
        commands/
            __init__.py
            _private.py # 以下划线开头文件不能用作管理命令
            my_commands.py # 这个就是自定义的管理命令脚本,文件名即为命令名
    tests.py
    views.py

这个布局是不能变的。这里注意,commands 文件夹下可以有多个py文件,基本上每个py文件的文件名,就是自定义管理命令的命令名称。所以,在一个commands里是可以创建出多条django-admin命令的。另外就是commands文件夹中,下划线开头的py文件,是不会被系统认定为django-admin命令的,所以像这种类型的文件都可以用来存储一些方法文件。

django-admin的具体定义:

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

from django.core.management.base import BaseCommand

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

    # 处理命令行参数,可选
    def add_arguments(self, parser):
       pass

    # 核心业务逻辑
    def handle(self, *args, **options):
        pass

这里注意?add_arguments() 这个函数中的参数,parser,它是个特殊的对象,使用方法类似于下面的演示。

from django.core.management.base import BaseCommand

class Command(BaseCommand):
    # 帮助文本, 一般备注命令的用途及如何使用。
    help = "Print Hello World!"

    # 给命令添加一个名为name的参数
    def add_arguments(self, parser):
        parser.add_argument('name')

    # 核心业务逻辑,通过options字典接收name参数值,拼接字符串后输出
    def handle(self, *args, **options):
        msg = 'Hello World ! '+ options['name']
        self.stdout.write(msg) 此时当你再次运行`python manage.py hello_world John`命令时,你将得到如下输出结果:

其实,关于这个参数,还有更多的用法,例如:

import datetime
import logging
import subprocess
import textwrap

from django.core.management.base import BaseCommand


DEFAULT_DAYS = 7
START_DATE = datetime.datetime(2018, 6, 24)
_BUILD_TREE = "/bldmnt/storage61/release"
_TERMINAL_METASTATES = ('failed')

logger = logging.getLogger('webapps')


class Command(BaseCommand):

    """
    This command takes 1 argument, buildtype
    """
    help = textwrap.dedent(__doc__).strip()

    def add_arguments(self, parser):
        # Named (optional) arguments
        parser.add_argument(
            '-b', '--buildtype',
            type=str,
            choices=('sb', 'ob'),
            required=True,
            help='Build type either SB or OB',
        )
        parser.add_argument(
            '--days', '-d',
            dest="days",
            default=DEFAULT_DAYS,
            help='Number of days to check storage. Default: %(default)s.',
            type=int,
        )

    def handle(self, *args, **options):
        """
        Entry point when management command is executed.
        """
        total_size = 0
        buildtype = options['buildtype']
        INTERVAL = options['days']
        END_DATE = START_DATE + datetime.timedelta(days=INTERVAL)
        DAYS_INTERVAL = datetime.timedelta(days=1)
        current_start = START_DATE

他完全和 python 的 parser 这个模块,用法一致。

关于这个模块的具体参数,及用法可以参考:

python之parser.add_argument()用法——命令行选项、参数和子命令解析器_夏普通的博客-CSDN博客_parser.add_argument(

添加 add_arguments 的方式,在写handle的时候,都是通过,options 取的,是当字典来用的。另外提一种,不添加?add_arguments 方法的方式,直接安位传参。

import os

from django.conf import settings
from django.core.management.base import BaseCommand


class Command(BaseCommand):
    def handle(self, *args, **options):
        os.system('%s %s' % (settings.FAB_CMD, ' '.join(args)))

    def run_from_argv(self, argv):
        parser = self.create_parser(argv[0], argv[1])
        options = parser.parse_args([])
        cmd_options = vars(options)
        cmd_options.pop('args', ())
        self.execute(*argv[2:], **cmd_options)

    def print_help(self, prog_name, subcommand):
        os.system('%s --help' % settings.FAB_CMD)

只需要重写?run_from_argv 这个方法,这样会让 opthions 的内容变为空字典。在manage.py 后使用的时候,就直接按位传参就可以了。

另外,再扯点fab命令,首先下载?fabric 包。

然后就是 fabric 的使用,命令:fab --fabfile? xxx.py? ?task:param? ?remote_machine_address

fab的使用,是必须有个配置文件的,这个文件放到工程的根目录且名为 fabfile.py 的时候,那么使用fab命令就可以不给 --fabfile 参数,如果是放到其他位置,或是叫其他名称,那就需要给 --fabfile 参数,以明确指定用哪个fab文件。

对fab的一些参数的说明,可以参考:Python Fabric模块详解 - 君无颜 - 博客园

看一个真实的fabfile:

from fabric.api import env, sudo, task, run
from fabric.context_managers import remote_tunnel, cd
from fabric.utils import puts



PROJECT_NAME = 'buildapi'
SERVICE_ROOT_SB = '/service/buildapi-sb'
SERVICE_ROOT_OB = '/service/buildapi-ob'
BUILDAPI_ROOT = '/build/mts/buildapi'

# Settings:
env.roledefs = {
    'sjc31': [
        
    ],
    'wdc': [
        
    ],
    'stage': [
        '
    ],
}
# Note: task(s) will be executed on hosts in the order listed
env.roledefs['all'] = (env.roledefs['wdc'] + env.roledefs['sjc31'])

set_common_settings()

# Tasks:
all = get_role_setter('all')
sjc31 = get_role_setter('sjc31')
wdc = get_role_setter('wdc')
stage = get_role_setter('stage')

sync = get_sync_task(PROJECT_NAME, BUILDAPI_ROOT)

restart_sb = get_restart_task(PROJECT_NAME, SERVICE_ROOT_SB)
restart_ob = get_restart_task(PROJECT_NAME, SERVICE_ROOT_OB)


@task
def deploy(rev=None, force=False, tunnel=False):
    """Deploy buildapi.  Usage: deploy[:rev=REVISION][:force=1][:tunnel=1]"""
    paragraph()
    puts(hl('Deploying buildapi...'))
    if sync(rev):
        py38env(tunnel)
        restart_sb(force)
        restart_ob(force)
    else:
        puts(warn('No need to restart.'))


@task
def py38env(tunnel=False):
    """Create/upgrade the py38 virtualenv.    Usage: py38env[:tunnel=1]"""
    if tunnel:
        tunnel_port = 10210
        with remote_tunnel(remote_port=tunnel_port,
                           local_host="build-artifactory",
                           local_port=80):
            sudo('/usr/bin/make -C %s -f ./py38env.mk '
                 'BUILD_ARTIFACTORY=127.0.0.1:%s'
                 % (BUILDAPI_ROOT, tunnel_port))
    else:
        sudo('/usr/bin/make -C %s -f ./py38env.mk' % BUILDAPI_ROOT)
    deploy_check()


@task
def deploy_check():
    """Deploy test for django admin check command if setup correctly"""
    with cd(BUILDAPI_ROOT):
        run('./manage_sb.sh check')

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-09-21 00:24:34  更:2022-09-21 00:28:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/26 14:17:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计