Django附带了各种命令行命令,可以使用django-admin.py
或者manage.py
调用。这些命令可以很方便的让你使用终端命令与应用程序进行交互,并且它还可以作为一个接口去执行定时任务。
介绍
查看完整的命令列表,
python manage.py help
其中包含你已经熟悉的startproject
、runserver
和collectstatic
等。
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
命令。