2013-03-11 78 views
1

我们总是从settings_test运行我们的测试,如下所示:./manage.py test someapp --settings = settings_test。问题是,记住添加选项有时是有问题的。(Django)创建一个管理命令,将覆盖BaseCommand中的默认设置

我想介绍一个只有管理命令test.py的通用应用程序。根据它在INSTALLED_APPS设置中的位置,它将覆盖默认值。在命令本身中,我想更改--settings选项的默认值。我怎样才能做到这一点?

我知道我可以创建一个类似于manage.py但使用settings_test而不是设置的local.py文件。然而,重点仍然是运行./manage.py,但是将settings_test作为默认值,而不是在./manage.py之后不断键入“--settings = settings_test”。测试someapp

+0

您是否考虑过为'manage管理写一个别名?py在shell中测试someapp --settings = settings_test'? – 2013-03-11 20:47:10

+0

这只是出于实际的目的:创建别名意味着每个正在从事项目工作的程序员都必须在其侧面创建别名,并且我想避免这种情况。我想将settings_test设置为默认设置,所以其他通常忘记添加该选项的程序员最终不会关注错误类型的错误,如果他们添加了错误,则不会出现错误类型。 – 2013-03-11 22:02:59

+0

为什么不用这样的常用命令创建一个Makefile并将其与您的存储库一起检查?然后你可以'make test_someapp'并完成它。 – mVChr 2013-03-11 22:05:31

回答

1

您可以通过实施来覆盖默认命令他们在你的应用程序(说:common_app)。

在common_app中创建一个management.commands包。 ,并在那里执行测试命令:

# this is commonapp/management/commands/test.py 
try: 
    from south.management.commands import test 
except ImportError: 
    from django.core.management.commands import test 


class Command(test.Command): 
    def handle(self, *args, **kwargs): 
     kwargs['settings'] = kwargs.get('settings', 'common_app.settings') 
     super(Command, self).handle(*args, **kwargs) 

这将使用settings.py文件中common_app如果没有“--settings =”标志中给出。但是你可以在“settings_test”中更改该字符串,并且会加载它可以在你的python路径中找到的第一个settings_test.py。

South也是这个命令覆盖太多,所以为了完整我加了南进口。但是,如果您的其他已安装的应用程序也覆盖了测试命令......您会明白。

不要忘记空的__init__.py文件来做'管理'和'命令'packages

RTFM有关Django自定义管理命令的更多信息。

+0

该代码并不像预期的那样工作 - 至少在Django 1.7中。 线 'kwargs [ '设置'] = kwargs.get( '设置', 'common_app.settings')' 似乎实际上从未改变的值,因为获得()发现的关键,这恰好值为None。 我已通过将其更改为: 'kwargs ['settings'] = kwargs.get('settings',None)或'common_app.settings'' HTH。 – pgcd 2015-05-22 07:44:45

+0

@pgcd请扩展 – 2015-05-22 07:49:35

+0

实际上还有另外一个问题:显然,它看起来像Django 1.7已经解析设置,当它处理() - 我只是试图设置kwargs ['settings']随机胡言乱语,它削弱愉快。 – pgcd 2015-05-22 07:55:06

1

经过多次尝试,我发现manage.py在实际管理命令被调用之前设置了足够长的时间,以至于在那里改变它们基本上是不可能的(据我所知)。 最后我决定,因为它似乎是确定以改变manage.py - 有默认的设置文件存在,例如 - 这将是一个合理的地方来解决这个问题,所以我实现它还有:

if __name__ == "__main__": 
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myapp.settings") 

    argv = sys.argv 
    try: 
     if argv[1] == 'test' and not any([k.startswith('--settings') for k in argv]): 
      os.environ["DJANGO_SETTINGS_MODULE"] = "myapp.test_settings" 
    except IndexError: 
     pass 

    from django.core.management import execute_from_command_line 
    execute_from_command_line(argv) 

这似乎按预期工作,我没有看到任何主要的缺点或问题 - 乐意予以纠正。

0

您可以覆盖@Chris Wesseling在他的回答中描述的django命令。

注:如果有正在扩展命令的其他应用程序,将在INSTALLED_APPS列表中的那些应用程序上面您的应用程序,即

  • 覆盖runserver命令,并且您使用'django.contrib.staticfiles',将您的应用程序前staticfiles应用
  • 覆盖test命令和你正在使用一个测试应用程序,即django_nose,同样,django_nose应用之前将您的应用程序