Django编写自定义manage命令

我们再使用Django写项目的时候,不可避免的我们会使用到一些manage命令,如django-admin startproject,python manage.py runserver …等命令,然后这些命令就能完成相应的事情。

但有时候Django自带的这些命令也不能满足我们的需求,我们就可以自己编写实现自己的一些需求的命令了。

例如:我们实现一个createuser的命令。我们在终端执行这条命令的时候,就会在数据库创建一个user对象出来。

准备工作:

首先新建一个Django项目,然后新建一个user的app,然后在user的models文件里面编写一个User模型。

from django.db import models

# Create your models here.
class User(models.Model):
    name = models.CharField(max_length=20)
    telephone = models.CharField(max_length=11)
    email = models.EmailField()

然后在settings.py文件里面配置好数据库的相关信息,因为我使用的是mysql数据库,所以需要配置,如果使用Django默认的sqlite数据库,就不用配置。

然后执行makemigrations和migrate命令,将模型映射到数据库中。

至此,我们就做好准备工作了。

注意: 这个app必须在settings.py文件中注册。否则会找不到自定义的命令

创建编写manage命令的文件

在Django中,我们想要编写自定义的manage命令,旧的遵循Django的规则来创建文件。

首先,我们在刚才新建的app下面新建一个包,(必须是包,不能是文件夹)这个包的名字为management,必须和这个一模一样,然后在management这个包下面再新建一个包,名字为commands,这样我们就创建好了存放manage命令文件的包,然后在这个包中新建一个python文件,文件的名字就为命令的名字,例如,我创建 了一个selfcommand的文件,也就是我创建的命令的名称为selfcommand
这个app最终的目录结构为:
Django编写自定义manage命令
这样,我们就创建好了编写代码的文件。

编写代码

首先,我们创建一个名为Command的类,这个类的名字必须为这个。然后继承自django.core.management.BaseCommand类。

from django.core.management import BaseCommand

class Command(BaseCommand):
    help = '创建一个user用户'

    def handle(self, *args, **options):
        pass

help这个变量可写可不写,这个变量的作用是在使用命令的-h--help参数时会显示出来的文字,在这里我们可以写入这条命令的作用,描述。

handle函数:这个函数是必须写的函数,我们使用这条命令的时候就会执行这个函数里面的代码。

因为我们这条命令的主要功能是创建一个user用户,所以我们首先导入User对象,然后开始编写代码。

from user.models import User
class Command(BaseCommand):
    help = '创建一个user用户'

    def handle(self, *args, **options):
        User.objects.create(name='aaa',telephone='1111111111',email='[email protected]')
        self.stdout.write('用户创建成功')

注意: 这里我们一般不使用print()打印信息,而是使用self.stdout.write来打印信息。

这样,我们就编写好了一条简单的创建一个user对象的命令。然后我们在终端执行命令:

python manage.py selfcommand(在创建的包的下面的文件的名字)

然后在终端就会打印出用户创建成功的信息,然后我们去数据库也能查看到创建的user对象的信息

Django编写自定义manage命令
但是,这个时候就会出现一个比较尴尬的问题,就是我们创建user用户的时候,肯定需要别人自己输入信息,但是我们并没有让别人自己输入信息,而是直接创建一个定死的user对象。所以,这个时候就需要我们给这条命令添加参数了。

如果想给命令添加参数,那么我们在这个类中就得新建一个方法,名为add_argument

class Command(BaseCommand):
    help = '创建一个user用户'

    def add_arguments(self, parser):
        parser.add_argument('name',help="指定name字段")  # name 必须参数,输入的第一个参数的值将赋值给name,必须参数
        parser.add_argument('-t','--telephone',help="指定telephone字段")   # 可选参数 -t 或 --telephone -t是简写形式。

    def handle(self, *args, **options):
        name = options['name']
        if options['telephone']:
            telephone = options['telephone']
        else:
            telephone = '11111111111'
        User.objects.create(name=name,telephone=telephone,email='[email protected]')
        self.stdout.write('用户创建成功')

在上面我们定义了两个参数,一个必须参数,一个可选参数,因此,我们再使用这条命令的时候必须传入name参数,而telephone参数可以不传,然后我们在handel方法中对得到的参数进行了处理。

python manage.py selfcommand ccc
python manage.py selfcommand ddd -t 18888888888

我们也可以使用python manage.py -h查看这条命令的帮助,也能看到我么自定义的参数。

我们再使用命令的时候,特别在使用一些刚接触不久的命令的时候,很容易出现非正确的使用命令,那么我们就需要抛出一个异常,告诉他命令使用错误了。

首先我们的导入一个类

from django.core.management import CommandError

例如,我们在传入手机号码的时候,如果位数超过了11位,那么我们就抛出一个异常:

def handle(self, *args, **options):
	name = options['name']
    if options['telephone']:
        telephone = options['telephone']
        if len(telephone) >= 11:
            raise CommandError("手机号码不能超过11位")
    else:
        telephone = '11111111111'
    User.objects.create(name=name,telephone=telephone,email='[email protected]')
    self.stdout.write('用户创建成功')

这里,我们就使用到了CommandError类来抛出了异常,从而保证了我们程序的健壮性了。

当用户输入的电话号码长度大于11位的时候,就会抛出一个异常而终止程序。

注意: 我们在参数中输入的值,在handel函数中都是以字符窜的形式得到,就算我们输入的是整数,也会变成字符窜的形式,如果想得到整数形式的值,我们可以在add_argument()中添加type=int参数。

示例:

parser.add_argument('id',help="user对象的id",type=int)

更多有关自定义manage命令的操作可以查看官方文档:https://docs.djangoproject.com/zh-hans/2.1/howto/custom-management-commands/