Question

I have a python/django project that I've set up for development and production using git revision control. I have three settings.py files:

-settings.py (which has dummy variables for potential open source project),

-settings_production.py (for production variables), and

-settings_local.py (to override settings just for my local environment). This file is not tracked by git.

I use this method, which works great:

try:
    from settings_production import *
except ImportError, e:
    print 'Unable to load settings_production.py:', e

try:
    from settings_local import *
except ImportError, e:
    print 'Unable to load settings_local.py:', e

HOWEVER, I want this to be an open source project. I've set up two git remotes, one called 'heroku-production' and one called 'github-opensource'. How can I set it up so that the 'heroku-remote' includes settings_production.py while 'github-opensource' doesn't, so that I can keep those settings private?

Help! I've look at most of the resources over the internets, but they don't seem to address this use case. Is this the right way? Is there a better approach?

The dream would be to be able to push my local environment to either heroku-production or github-opensource without haveing to mess with the settings files.

Note: I've looked at the setup where you use environment variables or don't track the production settings, but that feels overly complicated. I like to see everything in front of me in my local setup. See this method.

I've also looked through all these methods, and they don't quite seem to fit the bill.

Was it helpful?

Solution

There's a very similar question here. One of the answers suggests git submodules which I would say are the easiest way to go about this. This is a problem for your VCS, not your Python code.

OTHER TIPS

I think using environment variables, as described on the Two Scoops of Django book, is the best way to do this.

I'm following this approach and I have an application running out of a private GitHub repository in production (with an average of half a million page views per month), staging and two development environments and I use a directory structure like this:

MyProject
-settings
--__init__.py
--base.py
--production.py
--staging.py
--development_1.py
--development_2.py

I keep everything that's common to all the environments in base.py and then make the appropiate changes on production.py, staging.py, development_1.py or development_2.py.

My deployment process for production includes virtualenv, Fabric, upstart, a bash script (used by upstart), gunicorn and Nginx. I have a slightly modified version of the bash script I use with upstart to run the test server; it is something like this:

#!/bin/bash -e
# starts the development server using environment variables and django-admin.py

PROJECTDIR=/home/user/project
PROJECTENV=/home/user/.virtualenvs/project_virtualenv
source $PROJECTENV/bin/activate

cd $PROJECTDIR
export LC_ALL="en_US.UTF-8"

export HOME="/home/user"
export DATABASES_DEFAULT_NAME_DEVELOPMENT="xxxx"
export DATABASES_DEFAULT_USER_DEVELOPMENT="xxxxx"
export DATABASES_DEFAULT_PASSWORD_DEVELOPMENT="xxx"
export DATABASES_DEFAULT_HOST_DEVELOPMENT="127.0.0.1"
export DATABASES_DEFAULT_PORT_DEVELOPMENT="5432"
export REDIS_HOST_DEVELOPMENT="127.0.0.1:6379"

django-admin.py runserver --pythonpath=`pwd` --settings=MyProject.settings.development_1 0.0.0.0:8006

Notice this is not the complete story and I'm simplifying to make my point. I have some extra Python code in base.py that takes the values from these environment variables too.

Play with this and make sure to check the relevant chapter in Two Scoops of Django, I was also using the import approach you mentioned but having settings out of the repository wasn't easy to manage and I made the switch a few months ago; it's helped me a lot.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top