Table Of Contents

Previous topic

User Guide

Next topic

fabfile.py API

This Page

Customization

Custom deployment scripts

django-fab-deploy is intended to be a library, not a framework. So the preferred way for customizing standard command is to just wrap it or to create a new command by combining existing commands:

# fabfile.py
from fab_deploy import *
import fab_deploy.deploy

@run_as('root')
def install_java():
    run('aptitude update')
    run('aptitude install -y default-jre')

def full_deploy():
    install_java()
    fab_deploy.deploy.full_deploy()

fab_deploy.deploy.push() accepts callable ‘before_restart’ keyword argument. This callable will be executed after code uploading but before the web server reloads the code.

An example of ‘fab push’ customization

# fabfile.py
from fab_deploy import *
import fab_deploy.deploy

@inside_src
def rebuild_docs():
    with cd('docs'):
        run ('rm -rf ./_build')
        run('make html > /dev/null')

def push(*args):

    # run local tests before pushing
    local('./runtests.sh')

    # rebuild static files before restarting the web server
    def before_restart():
        manage('collectstatic --noinput')
        manage('assets rebuild')

    # execute default push command
    fab_deploy.deploy.push(*args, before_restart=before_restart)

    # rebuild developer documentation after pushing
    rebuild_docs()

Custom project layouts

User Guide describes standard project layout:

my_project
    ...
    config_templates <- this folder should be copied from django-fab-deploy
        ...

    reqs             <- a folder with project's pip requirement files
        all.txt      <- main requirements file, list all requirements in this file
        active.txt   <- put recently modified requirements here
        ...          <- you can provide extra files and include them with '-r' syntax in e.g. all.txt

    config.py        <- this file should be included in settings.py and ignored in .hgignore
    config.server.py <- this is a production django config template
    fabfile.py       <- your project's Fabric deployment script
    settings.py
    manage.py

django-fab-deploy does not enforce this layout. Requirements handling, config templates placement, local settings file names and project source folder can be customized using these options:

Example

Let’s configure django-fab-deploy to use the following layout:

my_project
    hosting                 <- a folder with server configs
        staging             <- custom configs for 'staging' server
            apache.config   <- custom apache config for staging server

        production          <- custom configs for 'production' server
            apache.config
            nginx.config

        apache.config       <- default configs
        django_wsgi.py
        nginx.config

    src                     <- django project source files
        apps
            ...

        local_settings.py   <- local settings
        stage_settings.py   <- local settings for staging server
        prod_settings.py    <- local settings for production server

        settings.py
        manage.py

    requirements.txt        <- single file with all pip requirements
    fabfile.py              <- project's Fabric deployment script

It uses subfolder for storing django project sources, single pip requirements file and different config templates for different servers in non-default locations.

fabfile.py:

from fab_deploy import *

# Common layout options.
# They are separated in this example in order to stay DRY.
COMMON_OPTIONS = dict(
    PROJECT_PATH = 'src',
    LOCAL_CONFIG = 'local_settings.py',
    PIP_REQUIREMENTS = 'requirements.txt',
    PIP_REQUIREMENTS_ACTIVE = 'requirements.txt',
    PIP_REQUIREMENTS_PATH = '',
)

def staging():
    env.hosts = ['user@staging.example.com']
    env.conf = COMMON_OPTIONS.copy()
    env.conf.update(
        REMOTE_CONFIG_TEMPLATE = 'stage_settings.py',
        CONFIG_TEMPLATES_PATHS = ['hosting/staging', 'hosting'],
    )
    update_env()

def production():
    env.hosts = ['user@example.com']
    env.conf = COMMON_OPTIONS.copy()
    env.conf.update(
        REMOTE_CONFIG_TEMPLATE = 'prod_settings.py',
        CONFIG_TEMPLATES_PATHS = ['hosting/production', 'hosting'],
    )
    update_env()