3

Is DEBUG == False supposed to mean that the app is running in production environment?

At least, that's what I see occasionally on the internet. But what do I put in settings.py then? Okay, I can put local settings to, say, settings_local.py and import it from settings.py. But if some settings depend on environment, than I've got to put them after import statement. There more I think about it, the more I don't like it. And you?

Community
  • 1
  • 1
x-yuri
  • 16,722
  • 15
  • 114
  • 161

3 Answers3

4

As an answer to the question:

Is DEBUG == False supposed to mean that the app is running in production environment?

DEBUG is a configuration that you define in your setting.py file.

  • If set to True, in case of un-handled exception it displays the complete stack-trace along with the values of all the declared variables.

  • If set to False, your server just returns the 500 status code without any stack-trace.

In production, you must have DEBUG set to False in order to prevent potential risk of security breach, and other information which you wouldn't want your user to know.


In order to use different settings configuration on different environment, create different settings file. And in your deployment script, start the server using --settings=<my-settings.py> parameter, via which you can use different settings on different environment.

Benefits of using this approach:

  1. Your settings will be modular based on each environment

  2. You may import the master_settings.py containing the base configuration in the environmnet_configuration.py and override the values that you want to change in that environment.

  3. If you have huge team, each developer may have their own local_settings.py which they can add to the code repository without any risk of modifying the server configuration. You can add these local settings to .gitnore if you use git or .hginore if you Mercurial for Code Version Control. That way local settings won't even be the part of actual code base keeping it clean.

Moinuddin Quadri
  • 46,825
  • 13
  • 96
  • 126
  • I think settings will not differ much, so I'm thinking about adding `DJANGO_ENV` environment variable, and using it in `settings.py` to determine which environment it is. – x-yuri Nov 09 '16 at 22:27
  • 1
    You may do it based on the `DJANGO_ENV`, but cleaner way is the way I mentioned. If settings won't differ much import the `production_settings.py` in `your_environment_settings.py` and override the configuration you want. By this your code will be modular and you won't have risk of modifying the production configuration while working on the local machine. + If you are working in large team, each developer can have there unique file which they can add to the `.gitinore` or `.hginore` file (based commit manager you use). They can use this on their local environment – Moinuddin Quadri Nov 09 '16 at 22:32
  • But passing `--settings` to every `django-admin`'s command is kind of... wordy. Should I then not put `./manage.py` into repository and create it in each environment manually? Or even create `manage.sh` instead? `#/usr/bin/env bash\nDJANGO_SETTINGS_MODULE=.settings django-admin "$@"`.On a side note, I wouldn't call point 2 and 3 advantages. They're more like how to live with what you suggest. Another benefit you could mention in your answer is that you're less likely to mess up production settings. – x-yuri Nov 10 '16 at 00:28
  • ...Or maybe `if [ -e /local_settings.py ]; then D...=.local_settings django-admin "$@"; else D...=.settings django-admin "$@"` – x-yuri Nov 10 '16 at 00:30
  • I've managed to come up with a [script](http://stackoverflow.com/a/40523668/52499) to ease using your approach. Consider merging it in your answer, please. Or feel free to criticize. – x-yuri Nov 10 '16 at 09:12
0

Use django-configurations to define a some alternative configurations and set the environment variable DJANGO_CONFIGURATION on each machine running the code to choose one.

You're free to define the classes however you'd like, but I'd recommend defining a Common class, which everything inherits from, and then Dev, Test, and Prod classes.

Anything involving system configuration should be pulled from environment variables (eg database connection, cache connection etc).

Have fun!

Will Hardy
  • 14,588
  • 5
  • 44
  • 43
  • I think `django-configurations` is overdoing it. Considering system configuration, can you elaborate? What exactly should be pulled from environment variables? Anything involving passwords? Keeping, e.g., database password out of `settings.py` is sure a good thing (at least, when `settings.py` is added to repository). But it's okay to leave there database user, I think. That is, I'm now thinking about leaving as much production settings as I can in `settings.py`. And override/add the rest in `local_settings.py`, which is not to be added to repository. Are you recommending `django-dotenv`? – x-yuri Nov 10 '16 at 13:20
  • Anything that is particular to a given machine should be in the environment. So database name, host, port etc shouldn't be fixed in code, you can of course provide defaults there and never override them in the environment. Reading from environment is built into `django-configurations`, no need for `django-dotenv` unless you want it. – Will Hardy Nov 10 '16 at 13:25
  • But what's the difference between overriding values using environment variables and by creating `local_settings.py` file? – x-yuri Nov 10 '16 at 17:10
  • 1. Some production environments only allow you to set (and change) environment variables, not add a new file in the middle of your package. It's good to operate as close as possible to production environment 2. you can process and validate the environment variables 3. I personally don't like custom code on dev machines, single code base with configuration keeps differences between production and dev contained. – Will Hardy Nov 16 '16 at 16:19
  • What do you mean by "process and validate environment variables"? – x-yuri Nov 16 '16 at 17:27
  • your codebase can inspect the local configuration values, clean them up, validate them, derive other configuration using them etc. With local_settings, you could still do this, but you would have to import them from a central settings module and do the processing after that. It gets messy. – Will Hardy Nov 21 '16 at 14:43
0

To add to @anonymous answer, here's the script (manage.sh) I came up with:

#!/usr/bin/env bash
DIR=$(dirname -- "$(readlink -f -- "$0")")
export PYTHONPATH="$DIR${PYTHONPATH:+:$PYTHONPATH}"
if [ -e <app>/local_settings.py ]; then
    export DJANGO_SETTINGS_MODULE=<app>.local_settings
else
    export DJANGO_SETTINGS_MODULE=<app>.settings
fi
django-admin "$@"

It uses <app>.local_settings if exists. Otherwise it falls back to <app>.settings.

Alternatively, you can just edit your manage.py.

x-yuri
  • 16,722
  • 15
  • 114
  • 161