我的编程空间,编程开发者的网络收藏夹
学习永远不晚

django如何自定义manage.py管理命令

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

django如何自定义manage.py管理命令

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

自定义的管理命令不仅可以通过manage.py运行,还可以通过Linux或Celery的crontab服务将其设成定时任务。本文主要讲解如何自定义Django-admin命令,并提供一些演示案例。

自定义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

注意:

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

编写命令代码

每一个自定义的管理命令本质是一个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

我们现在来看一个最简单的例子,希望定义一个名为hello_world的命令。这样当我们运行python manage.py hello_world命令时,控制台会打印出Hello World!字样。在app/management/commands目录下新建hello_world.py, 添加如下代码:


 from django.core.management.base import BaseCommand
 
 class Command(BaseCommand):
    # 帮助文本, 一般备注命令的用途及如何使用。
    help = "Print Hello World!"
 
    # 核心业务逻辑
    def handle(self, *args, **options):
        self.stdout.write('Hello World!')

注意:当你使用管理命令并希望在控制台输出指定信息时,你应该使用self.stdout和self.stderr方法,而不能直接使用python的print方法。另外,你不需要在消息的末尾加上换行符,它将被自动添加。

此时当你进入项目文件夹运行python manage.py hello_world命令时,你将得到如下输出结果:

现在我们来增加点难度,来通过命令行给hello_world命令传递一个name参数,以实现运行python manage.py helloworld John命令时 打印出Hello World! John。

现在修改我们的hello_world.py, 添加add_arguments方法,该方法的作用是给自定义的handle方法添加1个或多个参数。


 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命令时,你将得到如下输出结果:

如果你直接运行命令而不携带参数,将会报错,如下所示:

实际应用场景

前面的案例过于简单,我们现在来看两个自定义管理命令的实际应用案例。

案例1:检查数据库连接是否已就绪

无论你使用常规方式还是Docker在生产环境中部署Django项目,你需要确保数据库连接已就绪后才进行数据库迁移(migrate)的命令(Docker-compose的depends选项并不能确保这点),否则Django应用程序会出现报错。

这时你可以自定义一个wait_for_db的命令,如下所示:


 # app/management/commands/wait_for_db.py
 
 import time
 from django.db import connections
 from django.db.utils import OperationalError
 from django.core.management import BaseCommand
 
 
 class Command(BaseCommand):
     help = 'Run data migrations until db is available.'
 
     def handle(self, *args, **options):
         self.stdout.write('Waiting for database...')
         db_conn = None
         while not db_conn:
             try:
                 # 尝试连接
                 db_conn = connections['default']
             except OperationalError:
                 # 连接失败,就等待1秒钟
                 self.stdout.write('Database unavailable, waiting 1 second...')
                 time.sleep(1)
 
         self.stdout.write(self.style.SUCCESS('Database available!'))

定义好这个命令后每次在运行python manage.py migrate命令前先运行python manage.py wait_for_db即可。

案例2:周期性发送邮件

如果你是网站管理员,你肯定希望知道每天有多少新用户已注册,这时你可以自定义一条mail_admin的管理命令,将每天新注册用户数量以邮件形式发给自己,如下所示:


 # app/management/commands/mail_admin.py
 
 #-*- coding:utf-8 -*-
 from datetime import timedelta, time, datetime
 from django.core.mail import mail_admins
 from django.core.management import BaseCommand
 from django.utils import timezone
 from django.contrib.auth import get_user_model
 
 User = get_user_model()
 
 today = timezone.now()
 yesterday = today - timedelta(1)
 
 
 class Command(BaseCommand):
     help = "Send The Daily Count of New Users to Admins"
 
     def handle(self, *args, **options):
         # 获取过去一天注册用户数量
         user_count =User.objects.filter(date_joined__range=(yesterday, today)).count()
         
         # 当注册用户数量多余1个,才发送邮件给管理员
         if user_count >= 1:
             message = "You have got {} user(s) in the past 24 hours".format(user_count)
 
             subject = (
                 f"New user count for {today.strftime('%Y-%m-%d')}: {user_count}"
            )
 
             mail_admins(subject=subject, message=message, html_message=None)
 
             self.stdout.write("E-mail was sent.")
         else:
             self.stdout.write("No new users today.")

如果你在终端运行python manage.py mail_admin命令,你将得到如下输出结果:

注意:真正发送邮件成功需要设置Email后台及管理员,测试环境下可以使用如下简单配置:


 EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
 DEFAULT_FROM_EMAIL = "noreply@example.com"
 ADMINS = [("大江狗", "yunbo.shi@example.com"), ]

但是如果每天都要进入终端运行这个命令实在太麻烦了,我们完全可以使用Linux的crontab服务或Celery-Beat将其设成周期性定时任务task,这时只需要调用Django的call_command方法即可。


 # app/tasks.py, 可以任一app目录下新建task
 from celery import shared_task
 from django.core.management import call_command
 
 @shared_task
 def mail_admin():
     call_command("mail_admin", )

关于Django项目中如何使用Celery执行异步和周期性任务,请参加下篇Django进阶-异步和周期任务篇。

以上就是django如何自定义manage.py管理命令的详细内容,更多关于django 自定义manage.py管理命令的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

django如何自定义manage.py管理命令

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

linux中如何定义自己的命令

这篇文章主要介绍linux中如何定义自己的命令,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!学习如何创建别名:你可以将太长或难以记忆的命令打包成你自己构建的命令。命令别名Alias在 Linux shell 中指的是
2023-06-16

Django 自定义模型管理器类2个应用

class BookManager(models.Manager): # 改变查询集的结果集 def all(self): books = super().all() # QuerySet bo
2023-01-30

在Linux上如何自定义bash命令提示符

这篇文章给大家分享的是有关在Linux上如何自定义bash命令提示符的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。在 Linux 中自定义 bash 命令提示符在 bash 中,我们可以通过更改 $PS1 环境变
2023-06-16

如何在Linux中自定义bash命令提示符

前言 众所周知, bash (the B ourne- A gain Sh ell)是目前绝大多数 linux 发行版使用的默认 shell。本文将会介绍如何通过添加颜色和样式来自定义 bash 命令提示符的显示。尽管很多插件或工具都可以很
2022-06-04

Vue中如何自定义指令

这篇文章主要介绍Vue中如何自定义指令,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Vue中除了内置指令,也允许注册自定义的指令。自定义指令提供一种将数据的变化映射为DOM的行为例如:当我们想用一个函数表示焦点Vue
2023-06-04

如何用特定命令管理 Linux进程

这篇文章主要讲解了“如何用特定命令管理 Linux进程”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何用特定命令管理 Linux进程”吧!进程(process)是指正在执行的程序;是程序正
2023-06-16

如何使用 Composer 管理自定义 PHP 函数?

在 php 中使用 composer 管理自定义函数:创建自定义函数文件、在 autoload.php 中注册、配置 composer.json(添加“files”项)、安装依赖项。具体步骤包括:创建函数文件注册自定义函数配置 compos
如何使用 Composer 管理自定义 PHP 函数?
2024-04-22

vue如何自定义加载指令

本文小编为大家详细介绍“vue如何自定义加载指令”,内容详细,步骤清晰,细节处理妥当,希望这篇“vue如何自定义加载指令”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。前言用过element-ui的都应该知道,里面
2023-07-02

Vue中如何实现自定义指令?

Vue.js提供自定义指令功能,用于扩展其功能。创建自定义指令涉及定义指令对象并注册它。指令生命周期钩子函数在不同阶段调用。示例:v-highlight指令可高亮文本。自定义指令在创建可重用组件、扩展Vue功能、优化性能等场景中很有用。最佳实践包括保持简单、考虑性能、遵循命名约定和提供文档。
Vue中如何实现自定义指令?
2024-04-02

Angular中如何自定义创建指令

小编给大家分享一下Angular中如何自定义创建指令,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!指令介绍在 Angular 中有三种类型的指令:组件,有模板的指
2023-06-14

vue中的自定义指令如何使用

这篇文章主要介绍“vue中的自定义指令如何使用”,在日常操作中,相信很多人在vue中的自定义指令如何使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”vue中的自定义指令如何使用”的疑惑有所帮助!接下来,请跟
2023-06-29

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录