Set debug mode to false during an automatic deployment of a django website - django

What is the expected process when one wants to deploy a django website automatically by means of a continuous integration process: how can we set debug mode to false without editing the configuration file?

Generally there are three very common approaches to switch between production and development environments in Django applications:
Create a separate settings.py file with a different name and point to it using the DJANGO_SETTINGS_MODULE environment variable. Once setting a value to it, the expected settings file within the project folder will be ignored.
Use Python conditional statements to check for variables specific to your environment like if settings.DEBUG: and decide for other ones within that block of code.
Make a settings directory inside the project folder and create three additional files; one for common settings variables like common.py, and another two for local and production specific variables such as dev.py and prod.py. You can specify your __init__ to always import common.py and try to import one of the others if they are found.
Generally, you don't change anything in your code repository when deploying to production. It's the same code as on your local machine. The only difference is that your app server (gunicorn or uwsgi) is running with a different DJANGO_SETTINGS_MODULE environment variable.

Related

What is the recommended method for deploying Django settings to a production environment?

I have looked everywhere and all I could find was outdated or bits and pieces from several different sources, but none of them had a complete step of how to deploy Django to a production environment.
What I would like to see is the recommended way to deploy Django utilizing git, local and production settings.py, .gitignore specifically for Django.
How would I implement the settings to accommodate both environments and what should be added to the .gitignore file so that only necessary files are sent to the git repository?
Please note that I want to know best practices and up to date methods of using local and production settings.
Such questions arise when deploying Django apps.
Where should the settings be stored?
How can I properly implement the settings to accommodate both environments?
What sensitive information should be separate from the main settings?
Update 25/09/2016:
Thanks andreas for clarifying this and now I completely agree that there is no standard way of deploying Django. I went on a long research and found the most common used methods to deploy Django settings. I will share my findings with everyone who's having the same doubt.
Answering
Where should the settings be stored?
The settings are better accommodated within a settings module rather than a single settings.py file.
How can I properly implement the settings to accommodate both environments?
This is where the settings module comes in very handy because you can simply have environment independent settings and they are maintainable with git or any other version control.
What sensitive information should be separate from the main settings?
Sensitive information such as database, email, secret key and anything with authentication related information and as to how you will serve this private information secretly, I do recommend to use andreas suggestion.
You could either create a separate file at /etc/app_settings and make it very restrict or simply use environment variables from within the system.
.gitignore part
For the .gitignore part I found an awesome repo where you can get all sort of examples at https://github.com/github/gitignore.
I ended up using:
# OSX Finder turds
.DS_Store
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# Distribution / packaging
.Python
env/
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Django stuff:
*.log
my_app/settings/dev.py
bower_components
Because the answer ended up being so long I've created an article explaining every step of the way at Django Settings Deployment.
There is not one recommended way of deploying a Django app. The official documentation provides a guide for deploying with Apache and mod_wsgi. Some other options are a PaaS like Heroku/Dokku or deployment with Docker
It's common to divide your settings in different files. You could for example divide settings in four different files:
base file (base.py) - Common settings for all environments (every file below imports from this with from .base import *
development file (development.py) - settings specific for development, (DEBUG = True etc...)
production file (production.py) - settings specific for the production environment. (DEBUG = False, whitenoise configuration etc)
testing file (testing.py)
You can control what settings file is loaded with the environment variable DJANGO_SETTINGS_MODULE
It is also common recommended practice that you store secrets like the SECRET_KEY in environment variables. SECRET_KEY = os.environ.get('SECRET_KEY', None). Or check out the django-environ package.
Check out this repo for an example setup.

Django and loading config file before server starts

My django app is communicating with external server and before running django server i would like load some config file. Variables from this file are going to be used by some module while app is running
Problem is that config file can be located in many places.
My dream would be to run manage.py --cfg "/path/to/cfg/file.cfg" or
manage.py runserver --cfg "/path/to/cfg/file.cfg"
and some variables (like globals?) are going to be loaded and they are going to be avaible for django modules to be used. After django server shutdown those variables can dissapear
Is there some nice way to accomplish this?
There seem to be two parts to your problem:
How do I support changing which set of variables (as defined in a config file) are used for a given run
How can I load these variables such that they are visible to all the modules of my application.
The standard mechanism for doing the 2nd is to put stuff in settings.py.
If you do FOO="bar" in settings.py, in your module you can do:
from django.conf import settings
if settings.FOO == "bar":
# Do something
As far as how you can support multiple configurations, the first thing I could come up with is to rename your real settings.py to be real_settings.py and then create a series of config1_settings.py, config2_settings.py, config3_settings.py ... which look like:
from real_settings.py import *
from path_to_configX.py import *
where configX.py has all the values for whatever variables you want for configuration X.
You would then start django's built in server via:
manage.py runserver --settings=configX_settings.py
Note that doing this for a production server (where you can't as easily just pass something on the command line to kick it off) may be a bit trickier, but you're going to need to provide more use case details for that.

How to create environment variable config files for django with virtualenv?

I am writing an automation script to intialize django projects depends on a list of questions answered by the user from console.
Answers will be put into environment variables, such as SERVER_ENVIRONMENT is either 'development' or 'production'
The problem I am facing is the environment variables don't stick by using os.environ['var'], which means next time I run the project, those variables are not there, so I need to persist those variables somewhere on the disk inside the project.
What's the best strategy to do so? Ideally it should be automatic, works both by runserver command and uwsgi processes.
Can you instead generate file and import it from the settings.py.
e.g. in settings.py put
import env_config
Where env_config.py will be generated by your script, will not be version-controlled and will have all the os.environ definitions (or just plain global variables?)

How to maintain django different settings both on server and Github [duplicate]

This question already has answers here:
Using Git to keep different versions of a file locally vs. in the master repository
(2 answers)
Closed 9 years ago.
On the production server, I certainly need to have different settings, and are different from local settings.
Our opensource project is hosted on github. Thus the master branch is not production code (at least up to settings config).
Now, we got to host the project (django).. for that, The simplest solution I found is to create a new branch locally, setup production settings, add server git as remote, push that branch to the remote origin.
So, we can merge latest stable release whenever we want into production branch.. easily
But there is some issue in managing files in github..
Say the django settings are provided in "proj/settings.py". As local settings differ between system to system, we created "proj/local_settings.py" to overwrite system specific local settings (say, staticfiles location).. This file is ignored by Git using .gitignore
Now, if we use this file in production branch to config production settings, and as its currently ignored but Git.. we can't use it.
To push local_settings.py to production server from local production branch, we need to remove that location in .gitignore in that particular branch..
All is fine, accepted till here..
Here comes actual issue.
When we want to push new changes to production server, we first got to push them to production-local-branch, then to production server... but now,
.gitignore file changes to as present in release (i.e., local_settings.py is again added)
For this, I have to manually remove local_settings.py in gitignore of production-local-branch every time I merge something into it...
certainly the above all is a big mess..How do I handle it easily
What I'd suggest is to remove from your settings.py any settings that depend on where it is deployed. Put those settings into environment variables. For example:
STATIC_ROOT = os.environ.get('STATIC_ROOT')
then you need to set those environment variables before running the webserver.
On local:
STATIC_ROOT=`pwd`/static python manage.py runserver
On production depends on how you deploy, consult the documentation.
This principle of config into environment variables is exposed in the Twelve Factor App : http://www.12factor.net/config

deploying django site (wsgi)

Trying to use 2 different settings file for production and dev.
I set DJANGO_SETTINGS_MODULE='mysite.settings_production'
Works perfectly when running server with runserver
When I run it with apache though, apache doesn't seem to use the setting in the ~/.bash_profile and instead use os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") in the wsgi.py file
I guess it's maybe because apache is running on different user , not mine..
ok.. so it seems it's running as www-data on my ec2 ubuntu.
So I have to create the /home/www-data/.bash_profile and set the env variable?
It seems like so much hassle to use a different settings file.
Is there an obviously easier way to do this?
(I don't want to change the wsgi.py file, because it's source controlled)
Using bash_profile is completely the wrong way to do this.
The correct way is to use the wsgi.py file. However, since you don't want to do this (although I don't understand what it being version-controlled has to do with anything) then you can set environment variables directly in your Apache configuration using SetEnv:
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
Well, it's really wrong way. Common method to have separate settings for different environment is to store environment-dependent in local_settings.py (or whatever you name it) and imprort from settings.py
from local_settings.py import *
don't put local_settings.py under project repository as you will override it with each commit. If you want to keep a sample of local settings, put into a separate file, e.g. local_settings.py.example
You can import local settings at the beginning of settings.py (so settings.py settings would override local settings), or at the end, or have two local settings files for both cases.