Blog

The Digital Agency for International Development

Making it obvious which copy of a Django site you are using

By Hamish Downer on 22 January 2013

We frequently have multiple copies of a site running - the production server, the staging server and the local development copy. We want to be sure we are editing the correct site, and haven't switched sites by mistake. We certainly don't want to put some nonsense content into the production site to test some feature we're developing on the local copy. This is particularly easy to do when we have many tabs open in a browser, some of which have one site and some have another.

We're going to give the header bar of the side a different colour, and put some text in there. The text will tell us what environment we're in, if we need to check, while the colour should be something that suddenly looks "wrong" if we end up switching sites by mistake. Here's what our local dev copy looks like:

admin header

First we need to know which part of admin system we are in. We use the local_settings.py pattern - settings.py imports local_settings.py and we have a different copy of local_settings.py for each deployment environment - local dev environment, the shared development server, the staging server and the production server.

The key lines in our local_settings.py is:

# used in admin template so we know which site we're looking at
DEPLOY_ENV = "Local dev copy"
DEPLOY_ENV_COLOR = '#ff9900' # orange

Then we make that info available to templates. We do that using context processors. Ours looks like:

def deploy_env(request):
    """
    Add the deploy environment so we can show it when useful
    """
    import local_settings
    if hasattr(local_settings, 'DEPLOY_ENV'):
        deploy_env = local_settings.DEPLOY_ENV
    else:
        local_settings_file = os.path.join(os.path.dirname(__file__), os.pardir, 'local_settings.py')
        if os.path.exists(local_settings_file):
            deploy_env = os.readlink(local_settings_file).split('.')[-1]
        else:
            deploy_env = "Unknown deploy environment"
    extra_context = {'deploy_env': deploy_env}
    if hasattr(local_settings, 'DEPLOY_ENV'):
        extra_context['deploy_env_color'] = local_settings.DEPLOY_ENV_COLOR
    return extra_context

We add this to settings.py by adding to the TEMPLATE_CONTEXT_PROCESSORS setting:

TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    'main.context_processors.deploy_env',
)

Now we need to modify the admin templates so that they will use the information we have provided in extra_context. Django's admin system allows a lot of customisation that we can use to change the colour of the top bar, and add text there, depending on which copy of the site it is. We do that by customising admin templates. So you can copy from /django/contrib/admin/templates/admin/base_site.html to templates/admin/base_site.html The original is pretty simple:

{% extends "admin/base.html" %}
{% load i18n %}

{% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %}

{% block branding %}
<h1 id="site-name">{% trans 'Django administration' %}</h1>
{% endblock %}

{% block nav-global %}{% endblock %}

After we've modified it:

{% extends "admin/base.html" %}
{% load i18n %}

{% block title %}{{ title }} | {% trans 'My site admin' %} ({{ deploy_env }}){% endblock %}

{% block extrastyle %}
{% if deploy_env_color %}
<style>
#header{ background-color: {{ deploy_env_color }}; border-bottom: solid 3px #999; }
</style>
{% endif %}
{% endblock %}

{% block branding %}
<h1 id="site-name">{% trans 'My Site administration' %} ({{ deploy_env }})</h1>
{% endblock %}

{% block nav-global %}{% endblock %}

And that's all you need to do.