#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
(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
(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 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)
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.