14

I'm looking for a way to override/define some individual django setting from command line without additional settings files.

What I need right now is to set the DEBUG setting or logging level each time when I run my management command. But it would be nice to be able to set anything.

raacer
  • 5,302
  • 3
  • 27
  • 46
  • Do you want to set DEBUG every time `python manage.py runserver` called or you have your custom command `python manage.py foo` and you want to set DEBUG inside it? – Kirill Dec 19 '11 at 17:30
  • I want to set any setting for any command. Like this: `./manage.py --set="DEBUG=True" runserver`. Maybe the most easy way is to exec a command line parameter value right in settings.py. But I was hoping there is a way to not modify the source code at all. – raacer Dec 19 '11 at 18:26

4 Answers4

9

Here is my solution. Add the code below to the bottom of your settings file.

# Process --set command line option
import sys
# This module can be imported several times,
# check if the option has been retrieved already.
if not hasattr(sys, 'arg_set'):
    # Search for the option.
    args = filter(lambda arg: arg[:6] == '--set=', sys.argv[1:])
    if len(args) > 0:
        expr = args[0][6:]
        # Remove the option from argument list, because the actual command
        # knows nothing about it.
        sys.argv.remove(args[0])
    else:
        # --set is not provided.
        expr = ''
    # Save option value for future use.
    sys.arg_set = expr
# Execute the option value.
exec sys.arg_set

Then just pass any code to any management command:

./manage.py runserver --set="DEBUG=True ; TEMPLATE_DEBUG=True"
raacer
  • 5,302
  • 3
  • 27
  • 46
  • I think this is only possible way since Django doesn't offer any hook for preprocessing command-line arguments. I wonder why you need it? – Kirill Dec 21 '11 at 00:14
  • 1
    Hi Kirill. Thank you for your comment. I was not sure about this. Also what I don't like about my solution is the way I store the option value. But I have not found a better way to save the option between imports. – raacer Dec 21 '11 at 14:44
  • 1
    Why I need this is just because this is fast and easy way to tweak any setting during the development process. I can play with settings without modifying the settings file. And I can be sure I will not forget to change things back (this makes problem sometimes). Also it may be usefull for production. It is possible to tweak settings for individual task on cron/celery/etc. Right now what I need is to run some management command for me with the debug output, and for my partner with usefull output only. I don't feel like I should change the command for such needs. – raacer Dec 21 '11 at 14:52
  • You could use a local settings file. You most probably already have one, since you have different database login credentials in development as in production. This local settings file wouldn't be overriden by checkout and you don't risk forgetting settings in there. – András Gyömrey Aug 05 '16 at 07:16
  • 1
    @AndrasGyomrey The question is about the command line arguments. – raacer Aug 06 '16 at 11:32
2

In settings.py you can check for command line arguments, like this:

import sys

# for testing
if "--enable-wiki" in sys.argv:
    ENABLE_WIKI = True
    sys.argv.remove("--enable-wiki")

Usage:

./manage.py test --enable-wiki MyApp.tests
Ramon
  • 89
  • 1
  • 3
2

You can add custom option (ex. log level) to your command. Docs

Example:

from optparse import make_option

class Command(BaseCommand):
    option_list = BaseCommand.option_list + (
        make_option('--delete',
            action='store_true',
            dest='delete',
            default=False,
            help='Delete poll instead of closing it'),
        )
    # ...
Denis Kabalkin
  • 508
  • 4
  • 15
  • Thank you Denis. Sure I can. But I don't want to add this option to each command in each project. I'm looking for some more universal method. – raacer Dec 19 '11 at 15:34
-1

You can make your settings.py more aware of it's current environment:

DEBUG = socket.gethostname().find( 'example.com' ) == -1

Here's an option for different databases when testing:

'ENGINE': 'sqlite3' if 'test_coverage' in sys.argv else 'django.db.backends.postgresql_psycopg2',
gdonald
  • 984
  • 2
  • 12
  • 23