Django settings: raise KeyError, raise ImproperlyConfigured or use defaults?

时间:2017-06-15 09:31:16

标签: python django django-settings

Django expects you to use environment variables in settings.py to adapt to multiple environments (e.g. local, heroku, AWS).

I guess I should define -for instance- the username of the DB in an environment variable DB_USERNAME. How should I read it?

import os
DB_USERNAME = os.environ['DB_USERNAME']
DB_USERNAME = os.environ.get('DB_USERNAME')
DB_USERNAME = os.environ.get('DB_USERNAME', 'john')

Should I capture the KeyError and raise a ImproperlyConfigured myself? I prefer to make the app stop rather than run it using incorrect settings (defaults, people forgetting to set a variable,etc).

In the case of the defaults, it might even happen that john exists both loaclly and remotely, but with different permissions. It doesn't look very robust.

1 个答案:

答案 0 :(得分:2)

I would suggest a different approach to what you are doing.

I use the following process:

  1. Create a .env or .ini file with your environment variables in it:

    DB_USERNAME=myDB
    A_NUMBER=1
    ALLOWED_HOSTS=localhost, 127.0.0.1, my_host
    DEBUG=False
    MY_DJANGO_KEY=no_peeking_this_is_secret
    
  2. Use decouple.config -which will make your life easier- to read you .env/.ini file:

    on settings.py:

    from decouple import Csv, config
    
    DEBUG = config('DEBUG', cast=bool, default=True)
    A_NUMBER = config('A_NUMBER') # No cast needed!
    ALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=Csv(), default='')
    ...
    

That will allow you to have multiple .env or .ini files for each of your possible configurations and you won't have to worry about mixing up permissions etc.

Finally, I tend to use defaults with the lowest allowances possible (ex. look at my default allowed hosts which is an empty string).
But if there exists some very important variable that must be set correctly, then:

  • The config() method will raise a UndefinedValueError if a variable is undefined and no defaults are set.

  • We can therefore create a try:... except: block to anticipate that:

    try:
        SUPER_IMPORTANT_VAR = config('SUPER_IMPORTANT_VAR')
    except UndefinedValueError:
        print('Hey!! You forgot to set SUPER_IMPORTANT_VAR!!')