We always run our tests off of settings_test, like so: ./manage.py test someapp --settings=settings_test. The problem is that it's sometimes problematic to remember to add the option.
I'd like to introduce a common app that just has the management command test.py. Depending on it's placement in the INSTALLED_APPS setting, it will override the default. Inside the command itself, I'd like to change the default of the --settings option. How can I do that?
I am aware that I can create a local.py file that is similar to manage.py but with settings_test instead of settings. However, the point is to still run ./manage.py, but with having settings_test as default instead of constantly typing "--settings=settings_test" after ./manage.py test someapp
After several attempts, I found that manage.py sets the settings long enough before the actual management command gets called that it's basically impossible (as far as I can tell) to change them there.
Eventually I decided that, since it's seems to be OK to alter manage.py - there's your default settings file there, for instance - that would be a reasonable place to deal with this, so I implemented it there:
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)
This seems to work as expected and I don't see any major disadvantage or problem - happy to be corrected.
You can override default commands by implemeting them in your app (say: common_app).
Create a management.commands
package in common_app.
And implement a test command in there:
# 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)
This will use the settings.py
file in common_app if there's no '--settings=' flag in given. But you can change that string in "settings_test" and it will load the first settings_test.py it can find on your python path.
South does this command overriding too, so for completeness I added the south import. But if any of your other installed apps also override the test command... you get the idea.
Don't forget the empty __init__.py
files to make 'management' and 'commands' packages.
RTFM for more info on Django custom management commands.
You can override a django command as @Chris Wesseling describe in his answer.
Note: if there are other apps that are extending the command, move your app above those apps in the INSTALLED_APPS
list, i.e.
- to override
runserver
command and you are using 'django.contrib.staticfiles'
, place your app before staticfiles app
- to override
test
command and you are using a test app i.e. django_nose, the same, place your app before django_nose app