您好,欢迎来到化拓教育网。
搜索
您的当前位置:首页django如何自定义manage.py管理命令

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

来源:化拓教育网
django如何⾃定义manage.py管理命令

⽬录

创建⽂件夹布局编写命令代码实际应⽤场景

案例1:检查数据库连接是否已就绪案例2:周期性发送邮件每次在启动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 helloworldJohn命令时 打印出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=\"*******************\" ADMINS = [(\"⼤江狗\

但是如果每天都要进⼊终端运⾏这个命令实在太⿇烦了,我们完全可以使⽤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管理命令的资料请关注其它相关⽂章!

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuo9.cn 版权所有 赣ICP备2023008801号-1

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务