Skip to content

Instantly share code, notes, and snippets.

@guillaumepiot
Created February 7, 2014 10:58
Show Gist options
  • Save guillaumepiot/8860701 to your computer and use it in GitHub Desktop.
Save guillaumepiot/8860701 to your computer and use it in GitHub Desktop.
Django Weekend - Good practices

#Good practices for project management in Django

#Setting up the environment

Each Django project should be encapsulated in its own virtual environment, allowing us to manage the requirements and dependencies independently.

If you don't have Virtualenv installed, please visit this page and download the virtualenv package. For a simple installation:

$ cd virtualenv-1.11
$ sudo python setup.py install

If you have Virtualenv installed already, create a folder for your new project and start a new virtual environment inside it.

$ virtualenv my_project

Finally, we activate the virtual environment to get running:

$ cd my_project
$ source bin/activate

#Creating a new project

Install the latest version of Django:

(my_project) $ pip install django

Note: If you don't have pip installed, you can download it here: https://pypi.python.org/pypi/pip

Start a project from scratch and setup a repository

(my_project) $ django-admin.py startproject my_project

Then, you will need to create a repository on a provider such as GitHub or BitBucket.

$ git init
$ git add -A
$ git commit -m "first commit"
$ git remote add origin https://github.com/guillaumepiot/test_project.git
$ git push -u origin master 

Start a project from a repository

(my_project) $ git clone 

#Manage dependencies with a requirements file

We need to keep record of the packages that have been installed in our virtual environment, but even more importantly, save the packages that have been installed. A future install with a version mismatch could lead to unpleasant compatibility issues.

Pip has command that makes is easy to list the current dependencies:

$ pip freeze
Django==1.6.1
MySQL-python==1.2.5
Pillow==2.3.0
wsgiref==0.1.2

Now, we want to save those dependencies into a file for later use.

$ pip freeze > requirements.txt

This will create a requirements file from which we can re-install all the dependencies:

$ pip install -r requirements.txt

Pip will then go through all the packages required and install them one after the other.

#Multiple environment settings

In our project, we want to be able to manage settings for various environments. You will have a local environment, the one you develop on, and one or more live environment (eg: production & staging).

By using a default settings inheritance structure, we are able to override a selection of variables for a specific environment only.

So, in our project folder we replace settings.py by a folder called settings, which will contain an __init__.py file holding all our settings variables. Now, our settings are going to behave like a python module.

So a environment setup that point to project.settings will use the variables from __init__.py.

Now, if we want to setup a production set of variables, we create a production.py file which will contain only the variables which we want to override:

eg: from project.settings import * MY_VAR = 'test'

The production settings will inherit from all the __init__.py variables, and override the MY_VAR variable.

So, our folder structure will now look like this:

/settings
	__init__.py
	production.py

Deploying the application

Deploying your project manually, by FTP or SCP, can be time consuming process. It can also be prone to user error that could end in your website being down unexpectedly.

In order to minimise the risk of things going wrong, we are going to automate the process on deployment your project.

For this, we will use the Python Fabric library. Fabric allow the automation of task using Python code, which will allow us to connect to our server and then update & restart the website automatically.

Install the Fabric module:

$ pip install Fabric

Here's an example file:

(link to fabfile.py)

Running the application on specific settings

Most of our Django application are running on wsgi, with an Nginx server. To run our application, we setup an upstart script which will instantiate our site on a specific port. Then, we point our Nginx configuration to listen to that port to serve our website.

Here's an example upstart script:

description "uWSGI server for mysite.com" start on runlevel 2 stop on runlevel [016] respawn exec /usr/local/bin/uwsgi
--chdir=/var/www/mysite.com
--virtualenv=/var/www/mysite.com
--pythonpath=/var/www/mysite.com/mysiteproject
--socket 127.0.0.1:8888
--env DJANGO_SETTINGS_MODULE=mysiteproject.settings.production
--module 'django.core.handlers.wsgi:WSGIHandler()'
--master
--processes 1
--vacuum
--max-requests 500
--logto /var/www/mysite.com/logs/wsgi.log
--uid username
--gid groupname

You will notice that we use the environment setting DJANGO_SETTINGS_MODULE to point to the right settings for our production website.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment