如何创建自定义 Django 管理命令

Django附带了各种命令行命令,可以使用django-admin.py或者manage.py调用。这些命令可以很方便的让你使用终端命令与应用程序进行交互,并且它还可以作为一个接口去执行定时任务。

介绍

查看完整的命令列表,

python manage.py help

其中包含你已经熟悉的startprojectrunservercollectstatic等。

Type 'manage.py help <subcommand>' for help on a specific subcommand.
Available subcommands:
[auth]
    changepassword
    createsuperuser
[channels]
    runworker
[contenttypes]
    remove_stale_contenttypes
[debug_toolbar]
    debugsqlshell
[django]
    check
    compilemessages
    createcachetable
    dbshell
    diffsettings
    ...

[django_extensions]
    admin_generator
    clean_pyc
    clear_cache
    compile_pyc
    ...

[rest_framework]
    generateschema

[sessions]
    clearsessions

[staticfiles]
    collectstatic
    findstatic
    runserver

我们还可以通过创建一个management/commands目录,来自定义命令,并将它们包含在命令列表中,如下所示:

mysite/       <-- 项目目录
 |-- core/    <-- app目录
 |    |-- management/
 |    |    +-- commands/
 |    |         +-- init_data.py  <-- 自定义命令模块
 |    |-- migrations/
 |    |    +-- __init__.py
 |    |-- __init__.py
 |    |-- admin.py
 |    |-- apps.py
 |    |-- models.py
 |    |-- tests.py
 |    +-- views.py
 |-- mysite/
 |    |-- __init__.py
 |    |-- settings.py
 |    |-- urls.py
 |    |-- wsgi.py
 +-- manage.py

命令文件的名称也就是我们命令行执行命令的名称。例如,如果我们自定义命令文件时init_data.py,那么我们将通过以下命令取执行它。

python manage.py init_data

基本示例

在项目的某个app下创建目录文件: management/commands/what_time_is_it.py

from django.core.management import BaseCommand
from django.utils import timezone

class Command(BaseCommand):
    help = '显示当前时间'

    def handle(self, *args, **options):
        time = timezone.now().strftime('%X')
        self.stdout.write("现在是%s" % time)

一个Django管理命令由一个名称为Command的类组成,该类继承BaseCommand,命令代码应该定义在handle()方法中。

用法/输出:

(env) D:\qiaofinn\xk-backend>python manage.py init_data
现在是13:48:02

但是这与普通的python脚本有什么不同,或者他有什么好处?

主要优点是:所有的Django配置都已加载好了。这意味着你可以导入模型,使用Django的ORM对数据库进行查询,并与项目的所有资源进行交互。

命令参数

Django使用了argparse,它是Python标准库的一部分。为了处理自定义命令中的参数,我们应该定义一个名称为add_arguments的方法。

1、位置参数

这个示例是创建随机用户实例的命令。它需要一个名为total的位置参数,该参数定义该命令创建用户数量。

management/commands/create_users.py

from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
from django.utils.crypto import get_random_string

class Command(BaseCommand):
    help = '创建随机用户'

    def add_arguments(self, parser):
        parser.add_argument('total', type=int, help='表示要创建的用户数量')

    def handle(self, *args, **kwargs):
        total = kwargs['total']
        for i in range(total):
            User.objects.create_user(username=get_random_string(length=5), email='', password='123')

用法/输出:

(env) D:\qiaofinn\xk-backend>python manage.py create_users 5
jIQhE 123
MfReO 123
eOsBp 123
dqbAV 123
cSaQD 123

2、可选参数

可选参数prefix,该参数将被用于用户名字段的前缀。

management/commands/create_users.py

from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
from django.utils.crypto import get_random_string

class Command(BaseCommand):
    help = '创建随机用户'

    def add_arguments(self, parser):
        parser.add_argument('total', type=int, help='表示要创建的用户数量')
        parser.add_argument('-p', '--predix', type=str, help='用户名前缀')

    def handle(self, *args, **kwargs):
        total = kwargs['total']
        predix = kwargs['predix']
        for i in range(total):
            if predix:
                username = f'{predix}_{get_random_string(length=5)}'
            else:
                username = get_random_string(length=5)
            User.objects.create_user(username=username, email='', password='123')

用法:

# 创建10个用户名称带有前缀custom_user的用户

(env) D:\qiaofinn\xk-backend>python manage.py create_users 5 --predix system
# 或者
(env) D:\qiaofinn\xk-backend>python manage.py create_users 5 -p system
system_tREVG 123
system_qVNVu 123
system_lo9NP 123
system_B2zxg 123
system_2lVWb 123

如果使用前缀,则用户名字段将创建为system_2lVWb. 如果不使用前缀,用户名被简单地创建为2lVWb

3、标志参数

另一种类型的可选参数是标志,用于处理布尔值。假设我们添加一个--admin的标志,用来创建一个超级用户,或如果该标志不存在时创建一个普通用户。

from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
from django.utils.crypto import get_random_string

class Command(BaseCommand):
    help = '创建随机用户'

    def add_arguments(self, parser):
        parser.add_argument('total', type=int, help='表示要创建的用户数量')
        parser.add_argument('-p', '--predix', type=str, help='用户名前缀')
        parser.add_argument('-a', '--admin', action='store_true', help='创建admin用户')

    def handle(self, *args, **kwargs):
        total = kwargs['total']
        predix = kwargs['predix']
        admin = kwargs['admin']
        for i in range(total):
            if predix:
                username = f'{predix}_{get_random_string(length=5)}'
            else:
                username = get_random_string(length=5)

            if admin:
                User.objects.create_superuser(username=username, password='123')
            else:
                User.objects.create_user(username=username, password='123')

用法/输出:

(env) D:\qiaofinn\xk-backend>python manage.py create_users 2 --predix admin --admin
或者
(env) D:\qiaofinn\xk-backend>python manage.py create_users 2 --predix admin -a
admin_4C56m 123
admin_Xu5WV 123

3、任意列表参数

创建一个名为delete_users的新命令。在这个新命令中,我们将传递用户 ID 列表,并且该命令将从数据库中删除这些用户。

management/commands/delete_users.py

from django.contrib.auth.models import User
from django.core.management.base import BaseCommand

class Command(BaseCommand):
    help = '删除用户'

    def add_arguments(self, parser):
        parser.add_argument('user_id', nargs='+', type=int, help='用户id')

    def handle(self, *args, **kwargs):
        users_ids = kwargs['user_id']

        for user_id in users_ids:
            try:
                user = User.objects.get(pk=user_id)
                user.delete()
                self.stdout.write('User "%s (%s)" 删除成功。' % (user.username, user_id))
            except User.DoesNotExist:
                self.stdout.write('User id "%s" 不存在。' % user_id)

用法/输出:

(env) D:\qiaofinn\xk-backend>python manage.py delete_users 11 12 13
User "system_EvMnr (11)" 删除成功。
User "system_LfyfH (12)" 删除成功。
User "system_7JDTy (13)" 删除成功。

(env) D:\qiaofinn\xk-backend>python manage.py delete_users 11 12 14
User id "11" 不存在。
User id "12" 不存在。
User "system_UB0i9 (14)" 删除成功。

样式

我们可以通过为输出消息设置适当的颜色,所有可用样式的列表如下:

from django.core.management.base import BaseCommand

class Command(BaseCommand):
    help = 'Show all available styles'

    def handle(self, *args, **kwargs):
        self.stdout.write(self.style.ERROR('error - A major error.'))
        self.stdout.write(self.style.NOTICE('notice - A minor error.'))
        self.stdout.write(self.style.SUCCESS('success - A success.'))
        self.stdout.write(self.style.WARNING('warning - A warning.'))
        self.stdout.write(self.style.SQL_FIELD('sql_field - The name of a model field in SQL.'))
        self.stdout.write(self.style.SQL_COLTYPE('sql_coltype - The type of a model field in SQL.'))
        self.stdout.write(self.style.SQL_KEYWORD('sql_keyword - An SQL keyword.'))
        self.stdout.write(self.style.SQL_TABLE('sql_table - The name of a model in SQL.'))
        self.stdout.write(self.style.HTTP_INFO('http_info - A 1XX HTTP Informational server response.'))
        self.stdout.write(self.style.HTTP_SUCCESS('http_success - A 2XX HTTP Success server response.'))
        self.stdout.write(self.style.HTTP_NOT_MODIFIED('http_not_modified - A 304 HTTP Not Modified server response.'))
        self.stdout.write(self.style.HTTP_REDIRECT('http_redirect - A 3XX HTTP Redirect server response other than 304.'))
        self.stdout.write(self.style.HTTP_NOT_FOUND('http_not_found - A 404 HTTP Not Found server response.'))
        self.stdout.write(self.style.HTTP_BAD_REQUEST('http_bad_request - A 4XX HTTP Bad Request server response other than 404.'))
        self.stdout.write(self.style.HTTP_SERVER_ERROR('http_server_error - A 5XX HTTP Server Error response.'))
        self.stdout.write(self.style.MIGRATE_HEADING('migrate_heading - A heading in a migrations management command.'))
        self.stdout.write(self.style.MIGRATE_LABEL('migrate_label - A migration name.'))

 

定时任务

如果您有一项必须定期运行的任务,例如每周一生成报告。或者,假设您有一个 Web 抓取工具,它每 10 分钟从某个网站收集一次数据。您可以将此代码定义为管理命令,然后简单地将其添加到您服务器的 crontab 中,如下所示:

# m h  dom mon dow   command
0 4 * * * /home/mysite/venv/bin/python /home/mysite/mysite/manage.py your_command

每天凌晨 4 点执行your_command命令。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值