Arguably Django's killer feature, the admin offers a somewhat painless solution for customizing the it's look and feel. Django-Mingus implements a basic example of executing this, whereas Django-Grappelli and Ella are probably the most advanced open source solutions with custom Django admins.

The basics of customizing the Django admin

We're keeping it simple today. The two most prominent UI components of the Django admin are the login form and the Django admin's header, both contain opportunities to add client/product branding to the admin. The login form is the first impression, it's what the user sees first when invited to "go check out your new cms". And the header is located on every single view in the admin. So the least we can do is take care of these. First, let's start by taking a look at the Django-Mingus login view compared to the default login view.

Screenshot of default Django login view.

Screenshot of Mingus login view.

Getting your hands dirty

To customize any Django admin templates we need to first copy the template from Django source over to our local project. In this case, admin brand customization only requires customizing one template. But why do we copy one and not just edit the source file in the local instance of Django's repository? That's simple...

  • Customizations should be made local to your application and not Django source which could result in the customization being applied to all Django applications on your machine. This would be bad.

  • Reduce risk of merge conflicts when upgrading Django source. You're probably sticking with one stable version, but if you are running with trunk and constantly upgrading there is a chance you could run into merge conflicts and that's never fun.

  • Django is smart, obviously. So it helps you out with its template loaders and template directory settings discussed next.

Brief background on template loading

Django's default TEMPLATE_LOADERS are intelligent enough to first look at the current project's template configuration and tries to first load templates from those directories set in your project's template directories and if it can't locate them there it will then attempt to load the template from the related application, in this case the Django contrib application's template directory.

Essentially what this means is that by copying this template and the template directory structure (ex. templates/admin/base_site.html) to your project's template directory Django will locate your project's local version first and use that. If it fails to find the template in your local project then it will default to the associated application's template directory and look there. This is why we copy the template locally, so we can apply customizations without disrupting the source of the originating project.

Getting a move on

So let's get started. First we need to copy that one template we were just discussing...

#assumes your project already has a 'templates' and a 'tempates/admin' directory already created.

>> cp [src dir]/django/django/contrib/admin/templates/admin/base_site.html [project root]/templates/admin/base_site.html

Below is the original template base_site.html in it's entirety.

{% 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 %}

Next we're going to adjust the template we just copied, base_site.html. For this example we're reference Django-Mingus implementation in it's entirety.

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

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

{% block extrastyle %}
#header{ background-color: #333940; border-bottom: solid 3px #999; }

#branding h1{ color: #fff; }
.module h2, .module caption, .inline-group h2 { background:#ccc url(/admin_media/img/admin/nav-bg.gif) bottom left repeat-x; color: #333940; }
a.section:link, a.section:visited { color: #666666; }
{% endblock %}

{% block branding %}
<h1 id="site-name" > {% trans 'Mingus Blog Engine' %}</h1>
{% endblock %}

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

The differences to note are quite clear. First we've added the {% block extrastyle %} which allows us to add custom styles to our Admin theme. This code block exits Django's django/django/contrib/admin/templates/admin/base.html and allows any templates that inherits from it the option providing its own styles. This is a technique to remember if you're not acquainted with template overrides. By providing a {% block extrastyle %} in django/django/contrib/admin/templates/admin/base.html the Django template authors allow any other templates that extend this template to have a super easy, and intuitive way of overriding the base styles. You can see how this would become useful if you wanted to do the same for javascript, or any template fragments you can think of (i.e. right rail, meta data, etc). What I've done in the Django-Mingus custom extrastyle above is set some font colors, some background colors, and reused the Recent Action header's background image to give the below styles to the dashboard...

Screenshot of Mingus dashboard view.

Also to note is the branding block which provides... you guessed it — the Admin site's branding elements. In this case it's the title you see in the header of all the admin templates.

{% block branding %}
<h1 id="site-name">{% trans 'Mingus Blog Engine' %}</h1>
{% endblock %}

And that's it. That's all you need to do to get started with a basic customization of the admin. For quick switcharoo, let's say your client's name was a hot, new web photo sharing site named Flickrrr (yes, three r's for web 3.0, of course). This could be the quick brand customization you'd implement to make them feel right at home and cuddly when visiting their dashboard... or not.

Screenshot of example Flirckrrr dashboard view.


So that's it. This is the basic, simple customization we can do to make our clients comfortable by associating their brand with their new CMS, and although it terrificly simple to employ, I think this it's just as simple to overlook.

Too often we neglect the client's brand in favor of the default Django admin because it's easy. But all it takes is a few extra minutes and some CSS to customize the admin to meet your client's basic color scheme, and therefor giving them out-of-the-box comfort when visiting their hot, new Django admin - they won't be asking themselves "what is this Django administration" I'm looking at. And this is just the start. To really flex your muscles, like Lincoln Loop has done with their Gondola CMS or the Ella and Django-Grappelli projects mentioned above, you'd need to dive in a bit further of course but the authors of the Django Admin have done a terrific job at making even the complex customization easier than you might expect.

Have any Django admin customization tips or tricks? Post them below!