prettyprinted.net

Developing Django sites in multiple branches, part 2

This was posted March 29, 2008. It has received 0 comments and 0 pingbacks

Earlier this week I described the way I organize my web site projects in Bazaar in multiple branches and how each branch is organized in directories. I promised a follow-up the next day, but since I'm a lazy, lazy man I totally forgot it.

This post will describe two scripts that glue those four directories I showed you the last time together and form my development environment. In this post we will play around in the RSSEpisodes.com source code and create a new branch for a new feature that I have been planning.

I start out by creating a new branch for this feature:

$> bzr branch rssepisodes-trunk rssepisodes-gossip
$> ls
rssepisodes-calendar/   rssepisodes-gossip/   rssepisodes-links/   rssepisodes-regroup/
rssepisodes-trunk/

Bazaar creates a branch of the main developement tree and I can immediately cd into this new branch and start hacking:

$> cd rssepisodes-gossip 
$> source environment.sh 
$> manage.py runserver
Validating models...
0 errors found

Django version 0.97-pre-SVN-7209, using settings 'rssepisodes.settings_dev'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Now that's what I call agile! The only important part here is that I read the script environment.sh. This script must be executed from the root of my new branch since it uses the $PWD environment variable when setting its variables:

$> cat environment.sh
#!/bin/bash 
export PYTHONPATH="$PYTHONPATH:$PWD/python"
export PATH="$PATH:$PWD/scripts"
export DJANGO_TEMPLATE_PATH="$PWD/templates"
export DJANGO_STATIC_ROOT="$PWD/media"
export DJANGO_SETTINGS_MODULE="rssepisodes.settings_dev"

Pretty straightforward. In fact this setup is very straightforward. There's only a small bit of semi-magic going on in manage.py, which resides in scripts/ and that directory is now in my $PATH. Here's that small amount of magic:

$> cat scripts/manage.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from os import getenv
from django.core.management import execute_manager
if __name__ == "__main__":
    settings_module = getenv('DJANGO_SETTINGS_MODULE')
    settings = __import__(settings_module, fromlist=[settings_module.split('.')[-1]])
    execute_manager(settings)

This modified version of the default manage.py imports the correct settings module by using the environment variable that we set above. To accomplish this we need to invoke the __import__ function instead of the standard Python statement.

Now, you may have noticed the last time that I have two distinct settings modules; settings_prod.py and settings_dev.py. The former is a standard settings module, only renamed to emphasize that it is used in production. The latter actually imports everything from the production settings and only reassigns a few values. The interesting part is what I do with the template paths:

$> cat python/rssepisodes/settings_dev.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
from settings_prod import *

DEBUG = True
TEMPLATE_DEBUG = DEBUG

# overridden DATABASE settings go here

STATIC_ROOT = os.getenv('DJANGO_STATIC_ROOT')
TEMPLATE_DIRS = (
    os.getenv('DJANGO_TEMPLATE_DIRS'),
)

I use the environment variable DJANGO_TEMPLATE_DIRS set above as the template directory, and since this project also uses the static file server for development, I set the STATIC_ROOT variable which is used in urls.py when DEBUG is True.

And that is all. Now I really need to get some hacking done, I want this feature to go live tonight.

Leave a comment