fabric is a command management framework that allows you to easily setup commands that can run on both your local and external servers. This allows you to automate routine tasks that need to be performed on your local development server or on multiple computers.

hosts and virtualenvs

To get started using fabric, you'll need to install it using pip.

pip install fabric
In the root of your django project (in the same directory as your manage.py file) you can create a new file named fabfile.py. In this file, you can define different functions to perform routine tasks on your local and production servers. Here's an example of a basic fabfile that contains a wrapper for activating your virtualenv and a simple fabric command that will run your Django unit tests.
env.hosts = ['admin@example.com']
env.directory = '~/python/django_project/'
env.activate = 'source ~/python/django_project/bin/activate'

@_contextmanager
def virtualenv():
    with cd(env.directory):
        with prefix(env.activate):
            yield

def test():
    with virtualenv():
        local('./manage.py test')

You can then execute this command by typing

fab test

By running that command, you activate your virtualenv, and then run the manage.py test command on your local machine. You may be thinking that this seems like a lot of work just to run the django test command, but by using fabric, you are able to string multiple commands together.

coverage

This fabric command will run your unit tests and then run the coverage command to tell you how many lines of code in your project were executed while running the tests.

def coverage():
    with virtualenv():
        local('coverage run --source=app --omit="*/migrations/*" ./manage.py test')
        local('coverage report -m')

Where --source=app is the name of the Django app you want to test. Here I am passing some additional arguments to the coverage command to omit considering anything in my migrations files. I can run this command by typing

fab coverage

sync local db

This command is a little more complicated but showcases some of the strengths of using fabric. Here I am logging into the remote server and exporting a copy of the production database. Then I am secure copying that file back to my local computer and updating my local database. After running that command, my local development environment will be using an exact copy of the database from my production server. This is useful for debugging and testing.

def sync_local_db():
    run('/usr/bin/mysqldump -u username -h mysql.example.com -p database_01 | gzip > ~/mysql_bkups/tmp/database.sql.gz')
    get('~/mysql_bkups/tmp/database.sql.gz', '~/python/django_project/database.sql.gz')
    local('gunzip ~/python/django_project/database.sql.gz')
    local('mysqladmin -u root -proot drop database_01')
    local('mysqladmin -u root -proot create database_01')
    local('mysql -u root -proot database_01 < ~/python/django_project/database.sql')
    local('rm -f ~/python/django_project/database.sql')

deploy

This command will deploy my website to the production server. First, it runs my unit tests, then prompts me to commit any changed files to my master git branch, then pushes the master branch of my local repository to my production server, then restarts the services on my remote server. One nice feature about fabric is that if any of the steps fail, it will exit and won't execute the rest of the commands. So for example, if my unit tests don't pass, I will see the output of the tests printed to the shell and fabric will exit. It will not try to commit my changes and push the repository to the production server.

def deploy():
    with virtualenv():
        local('./manage.py test')
        local('git commit -a')
        local('git push production master')
        restart_remote()

There are more examples and a short tutorial on the fabric documentation website.