带有附加参数的自定义django管理命令

时间:2015-10-01 14:18:27

标签: python django testing

我的团队定期运行自定义测试套件。当我们想要运行整个事情时,我们会这样做

./manage.py test --keepdb --failfast --settings=AE.test_settings

当我们想要在特定应用上运行测试时,我们也会这样做,但应用名称包含。

我想创建一个自定义管理命令,在调用时,它将运行默认测试套件,但附加--keepdb, - failfast和--settings = AE.test_settings参数。理想情况下像

./manage.py aetest

也可以使用应用名称运行,例如

./manage.py aetest registration

与运行

相同
./manage.py test registration --keepdb --failfast --settings=AE.test_settings

到目前为止我的尝试是

from django.core.management.base import BaseCommand, CommandError
from django.core import management

class Command(BaseCommand):

    def handle(self, *args, **kwargs):
        positional_arguments = [
            '--keepdb',
            '--failfast',
            '--settings=NJ.test_settings',
        ]
        for item in args:
            positional_arguments.append(item)
        keyword_arguments = {
            'settings': "AE.test_setings",  
        }
        keyword_arguments.update(kwargs)
        management.call_command("test", *positional_arguments, **keyword_arguments)

如果我尝试传递更多的位置参数,我的命令会以暗示它们永远不会传递的方式出错。并且关键字参数永远不会进入call_command(该命令使用我的默认settings.py文件运行)

我知道如何让这个管理命令接受额外的位置和关键字参数,但是会自动附加所需的参数吗?

谢谢!

更新

我被赋予了BaseTestCommand子类化的好主意。虽然这似乎适用于True / False变量,但传递设置变量似乎不起作用。如果我使用以下代码:

class Command(BaseTestCommand):
    def handle(self, *test_labels, **options):
        options['failfast'] = True
        options['keepdb'] = True
        options['settings'] = "AE.test_settings"
        print(options)

        super(Command, self).handle(*test_labels, **options)

运行我的新命令使用failfast和keepdb,但它仍然使用我的项目的默认settings.py。知道为什么会这样吗?

旁注:使用--settings = AE.test_settings运行新命令就像魅力一样

1 个答案:

答案 0 :(得分:3)

您可以继承Django test命令并覆盖handle方法来设置所需的选项。

from django.core.management.commands.test import Command as BaseTestCommand


class Command(BaseTestCommand):
    def handle(self, *test_labels, **options):
        options['failfast'] = True
        options['keepdb'] = True
        options['settings'] = 'NJ.test_settings'

        super(Command, self).handle(*test_labels, **options)

至于为什么你的代码不起作用,这是因为你滥用了call_command函数。每个命令选项(以--开头)都必须作为关键参数传递,即使它是布尔值,您的handle方法应该是:

def handle(self, *args, **kwargs):
    kwargs.update({
        'settings': 'NJ.test_settings',
        'keepdb': True,
        'failfast': True
    })
    management.call_command("test", *args, **kwargs)