Ben Emson

How To Set Up and Build a Django Web Site

This article outlines how to set up your new Django site from scratch. I tend to use Dreamhost Web Site Hosting so there will be a few notes specific to them.

If you are unsure how to set up Python and Django using Dreamhost then checkout my previous article.

I hope you find it useful and drop me a comment if you have any questions.

Create the new site

Create a project directory

$ mkdir -p mysite-project/
$ cd mysite-project/

Create you new site:

$ startproject mysite

Now create the following directories:

$ mkdir -p mysite-project/settings
$ mkdir -p mysite-project/
$ mkdir -p mysite-project/
$ mkdir -p mysite-project/
$ mkdir -p mysite-project/

Initialise git

$ cd mysite-project/
$ git init
$ touch .gitignore

Add the following:


Add WSGI file

The following should be carried out from this directory:

$ cd mysite-project/

Add the file to mysite-project/ directory:

import sys, os
if sys.hexversion < 0x2060000: os.execl("/home/myuser/opt/python261/bin/python2.6", "python2.6", *sys.argv)



required if you are using VirtualEnv, to get Passenger to use local Python environment.


INTERP = "/home/myuser/virtual/bin/python2.6" if sys.executable != INTERP: os.execl(INTERP, INTERP, *sys.argv)


os.environ['DJANGO_SETTINGS_MODULE'] = "mysite.settings" import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler()

Create the public/appmedia directory in this directory to. Create tmp/restart.txt

Set up the VirtualEnv Environment

Move to the mysite-project directory. Ensure that you have virtualenv installed on your local system:

$ cd mysite-project
$ pip install virtualenv

Create the virtual/ directories using virtualenv:

$ virtualenv ./virtual

Create a symbolic link to the activate executable.

$ ln -s ./virtual/bin/activate ./activate

NB: if you rename your mysite-project directory you may well need to delete the virtual directory and activate symbolic link and recreate them using the previous virtualenv steps.

You can check which Python site packages being used with this command:

$ python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"

Create Local Dev Database

Change directory to the scripts directory in mysite-project/

$ cd mysite-project/
$ touch scripts/create-db.sql
$ touch scripts/drop-db.sql


create database mysite_com_dev;
grant all on mysite_com_dev.* to 'root'@'localhost';


drop database mysite_com_dev;

Now create the database

$ mysql -u root < scripts/create-db.sql

Set up the Django Project Files

Make the following changes to the file.

import sys
import os
import os.path
import socket

PROJECT_ROOT = os.path.realpath(os.path.dirname(file)) sys.path.insert(0, os.path.join(PROJECT_ROOT)) # needed because of shared hosting PYTHONPATH problems

MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'public/appmedia/')

MEDIA_ROOT = '/full/local/path/to/appmedia/'

MEDIA_URL = '/appmedia/'


TEMPLATE_DIRS = ( os.path.join(PROJECT_ROOT, 'templates').replace('\','/'), )

INSTALLED_APPS = ( 'django.contrib.admin', # add this 'django.contrib.admindocs', # and this 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', )

Add this to the bottom to import your local settings

try: from settings_local import * except ImportError: pass

Now we need to create a file in the same directory as the main file:

$ touch

Then add your default settings (most probably your dev settings):

DATABASE_ENGINE = 'mysql'   
DATABASE_NAME = 'mysite_com_dev' DATABASE_USER = 'root'
DATABASE_HOST = 'localhost'

As we will be using multiple environments we need to have different configurations for each environment. There are a number of ways to do this, however the DRYist and easiest is to have a main settings file that imports different settings according to the environment.

Change directory to the mysite-project/settings directory, and create the appropriate settings files - we will have a dev, staging and production file as well as the main one:

$ cd mysite-project/settings
$ touch; touch; touch

Now add the appropriate settings to these files database settings. Note that these settings will overwrite the settings in the main settings file.

Adding South to Your Application

For detailed installation instructions see

Note, for MySQL databases, you should install South to a new instance of your MySQL database and not an existing or legacy database. This is because South won't update it's self when you run: python migrate

Quick installation.

Add South (Note the capital 'S') to your pip requirements.txt file, and pip install it:

$ pip install -r requirements.txt

Or just run:

$ pip install South

Install the south (Note lowercase 's') into your project file. e.g.:


Now syncdb with your database so that your App knows about South.

$ python syncdb

You should get an output similar to this:

Creating table south_migrationhistory

 > django.contrib.admin
 > django.contrib.auth
 > django.contrib.contenttypes
 > django.contrib.sessions
 > django.contrib.sites
 > django.contrib.markup
 > south
 > tagging

Not synced (use migrations):
(use ./ migrate to migrate these)

Finally you need to tell South what Apps you want it to manage (in terms of migrations). So for example say you have an App called 'firepages', then run:

$ python startmigration firepages --initial

This will create a migrations directory and will allow South to manage all the models in that App:

  Creating migrations directory at '/mypath/mysite-project/'...
  Creating in '/mypath/mysite-project/'...
   + Added model 'firepages.Group'
   + Added model 'firepages.Category'
   + Added model 'firepages.Page'

Note that because you will be uploading this new migrations directory you shouldn't need to run this command on the server.

You will now need to execute the following command to migrate forward:

$ python migrate

Now if you want to change your database do the following:

  1. Modify your model. e.g. add / remove fields
  2. Tell South to create a migration: python startmigration myapp name-of-my-migration --auto
  3. Execute the migration: python migrate


Use the following imports:

from django.conf import settings
from django.contrib import admin


At the bottom add a new URL path so that the site can get access to the appmedia, NB don't forget to add a staging and production version to:

# simple trick to use local css files for development.

(Just make sure DEBUG=False in production!!!)

if settings.DEBUG: urlpatterns += patterns('', url(r'^appmedia/(?P<path>.*)$', 'django.views.static.serve', { 'document_root': settings.MEDIA_ROOT }), )

Now add the following URLs:

urlpatterns = patterns('',
    #Admin URLS
    # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
    (r'^admin/', include(,

#Home URL
(r'^$', include(''),


You may want to change the admin URL pattern to be something else. This will make the admin area more obscure thus helping to prevent hacking. e.g. mylogin

Add a file

In the mysite-production/ directory add a file with the following:

from django.http import HttpResponse

import settings

def hello(request, path='none'): """quick hello test""" return HttpResponse("Quick test, PROJECT_ROOT: %s<br/>URL path: %s" % (settings.PROJECT_ROOT, path))

Sync the DB and Start the Server

Navigate to the mysite-project/ directory

Start the virtual environment:

$ . ../../activate
(virtual)$ python syncdb
 create a user 
(virtual)$ python runserver

Now open a browser and point it at this URL:

$ open http://localhost:8000

It should display your hello view results.


Add a requirements.txt file to the following directory:

$ touch mysite-project/mysite/requirements.txt

Add in any requirements e.g. django-tagging

$ echo mysite-project/mysite/requirements.txt << django-tagging

Execute and add requirements:

$ pip install -r requirements.txt

Local Apps Directory

Create an apps directory in the root of your project folder. Then tell your file about it:

  sys.path.insert(0, os.path.join(PROJECT_ROOT, "apps"))

Now any apps that you want in here and not in your "pip install" directory just add them and they will be found.

RequestContext on All Views

All your views should implement a RequestContext variable, but first you will need to add the following CONTEXT_PROCESSORS to the file:

    'django.core.context_processors.debug', # passes the DEBUG variable to the template
    '', # passes the MEDIA_URL to the template
    'django.core.context_processors.request', # passes the request object to the template

Now Make sure that you pass the RequestContext to the render.

def home_page(request):
    """display home page"""
    template = "page_home.html"
    return render_to_response(template, { 'foo':'bar' }, context_instance=RequestContext(request))

This will allow you to use generic templates, and also get a handle on certain variables in the template.

Page Specific Menus

See this article for more information:

Django doesn't out of the box provide a current_page variable like Ruby on Rails - but it is easy enough to implement.

You will need to have the 'django.core.context_processors.request', setting set in the template context processors as specified above.

You will also need to create a module called templatetags with a file in it. Now add a file called

from django import template

register = template.Library()

@register.simple_tag def link_to(request, pattern, url, name): import re if, request.path): return '<span class="active">%s</span>' % name return '<a href="%s">%s</a>' % (url, name)

Now in your template load this template tag and call it like this:

{% load active_menus %}
<li>{% link_to request "^/$" "/" "home" %}</li>
<li>{% link_to request "^/software/$" "/software/" "software" %}</li>
<li>{% link_to request "^/books/$" "/books/" "books" %}</li>

Template Includes

When creating an include template file give it a name starting with an underscore e.g. _nav.html

Add a Sitemap to Your Site

Add the following to your file in the INSTALLED_APPS section:


Now check that you have the following installed also.

This should be in the TEMPLATE_LOADERS:


Make sure you’ve installed the sites framework. Also make sure that you have set the site domain name and description correctly in the sites project in the Admin Panel. It should not be, but something like:

Create a file in your project. This file should contain something like:

from django.contrib.sitemaps import Sitemap
from myproject.models import ProductPage, ProductCategory

class ProductPageSitemap(Sitemap): changefreq = "never" priority = 0.5

def items(self):
    return ProductPage.objects.all().filter(published=True)

class ProductCategorySitemap(Sitemap): changefreq = "never" priority = 0.5

def items(self):
    return ProductCategory.objects.all()</code></pre>

Now add the following to your file:

from myproject.sitemaps import *

from django.contrib.sitemaps import FlatPageSitemap, GenericSitemap

sitemaps = { 'product_pages': ProductPageSitemap, 'product_categories': ProductCategorySitemap, }

urlpatterns = patterns('', (r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}) )

Adding a new App

$ python startapp myappname

Add myappname to your file INSTALLED_APPS Now create some models in your myappname/ file.

Then run a syncdb:

$ python syncdb
OR to see the SQL
$ python sql myappname

Now if you want to add South migrations:

$ python startmigration myappname --initial

Installing PIL

PIL should not be installed as part of the requirements.txt file, as you will need to compile libjpeg first.