Customizing Django's Admin Templates and Media When Using the Built-In Development Web Server

At work today, Sean was playing around with creating a Django app and wanted to use the django-grappelli project to get a cool look for Django’s admin. I warned him against using the instructions included in the project since if you are using Django from an svn checkout then it will break any future svn updates with an error message something like this:

working copy does not exist in repository

So, we started working on a way around this for a local dev environment. We knew we could override the admin templates easily but hadn’t really seen anything about how to override the admin media. Between the two of us, we got it working and figured putting it into writing for future reference would be a good thing.

Step 1

First, check out the django-grappelli project. I’m putting mine in the src directory in my home directory:

$ cd ~/src
$ pwd
/Users/chris/src
$ svn checkout http://django-grappelli.googlecode.com/svn/trunk/ django-grappelli

Step 2

In your project’s settings.py add a template directory to the templates directory in the django-grappelli directory you created above:

TEMPLATE_DIRS = (
'/Users/chris/src/django-grappelli/templates',
)

Also in settings.py change the ADMIN_MEDIA_PREFIX to use the full URL to the server that manage.py’s runserver command will create and append that with a path you want to use. This doesn’t need to relate to any file system path since you’re just going to use it in a urlconf with a static view.

ADMIN_MEDIA_PREFIX = 'http://127.0.0.1:8000/media/admin/'

Step 3

In your project’s urls.py comment out the lines to enable the admin and add a urlpattern to serve the admin media using the web path you used above from the file system path of the media directory in the django-grappelli project you created in the first step.

In my case, I’m using http://127.0.0.1:8000/media/admin/ as my ADMIN_MEDIA_PREFIX which is a web path of /media/admin/. Since Django strips off the initial slash, your regex to match it would be r'^media/admin/(?P<path>.*)$'. You’ll send these requests to the django static serve view and pass in the document_root which is the file system path to django-grappelli’s media directory. Your urls.py should now look something like this:

from django.conf.urls.defaults import *

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns(”,
(r'^admin/(.*)', admin.site.root),
(r'^media/admin/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/Users/chris/src/django-grappelli/media'}),
)

Finally

Now, just do ./manage.py runserver in your project directory and browse to http://127.0.0.1:8000/admin/ and you should see Grappelli’s sweet styles looking back at you.

Notes

The key to making this work is using a full URL instead of an absolute or relative URL for your ADMIN_MEDIA_PREFIX. This allows Django to use your normal urlconf to serve up the media with the static serve view.

This is designed to work in a local dev environment using Django’s built-in server. Don’t use this in production—serve your media using nginx, Apache, etc.

There is probably a better way to do this and suggestions are welcome.

9 Comments

  1. Posted December 12, 2008 at 9:19 am | Permalink

    this is a very good point. we personally use the latest official django-version with grappelli. using an svn checkout probably breaks the grappelli-styles (because of some smaller changes made by wilson recently). nevertheless, I´d definitely prefer a solution where we don´t have to override djangos media- and templates-directory.
    I´ll include a link to this article to the grappelli-documentation …

  2. Posted December 12, 2008 at 9:38 am | Permalink

    @patrick: cool, thanks!

  3. Posted December 16, 2008 at 9:14 pm | Permalink

    Not enough gets written about admin customisations. Nice piece.

    There's been some kind of train-wreck in your URL patterns, though. Somebody's run through and dropped in some HTML tags (an "em" element) in place of reg-exp strings.

  4. Posted December 16, 2008 at 9:20 pm | Permalink

    @Malcolm: yikes! Thanks for pointing that out. The train has been put back on track :-)

  5. Posted December 18, 2008 at 1:16 pm | Permalink

    finally got it to work.

    it is important to make it the last (or in my case, second) template directory listed… so that, in your regular template directory, you can override the shortcut/navigation html.

  6. patrick
    Posted March 14, 2009 at 1:53 pm | Permalink

    I've been rethinking this issue lately. Although I´m no expert with using subversion, isn´t it possible to remove a directory (e.g. /media/) from future svn-updates? That´d ensure that django-updates won´t be broken when using Grappelli … I've just checked the subversion online-docs, but unfortunately I didn´t find an answer.

  7. Posted March 16, 2009 at 8:27 am | Permalink

    @patrick: it looks like this will be possible in v1.6 of subversion according to this blog post.

  8. Posted January 15, 2010 at 12:09 am | Permalink

    This is brilliant, thanks so much. The one thing I didn't like in this solution was that you're hard-coding a full path in urls.py, which doesn't work across dev and production environments. To fix this I put this in local_settings.py:

    LOCAL_GRAPPELLI_MEDIA = '/path/to/grappelli/media'

    and then in urls.py:

    {'document_root': settings.LOCAL_GRAPPELLI_MEDIA}

  9. Roman
    Posted May 13, 2010 at 6:39 pm | Permalink

    Good post. But if you try to change from step2:
    ADMIN_MEDIA_PREFIX = 'http://127.0.0.1:8000/media/admin/'
    to ADMIN_MEDIA_PREFIX = '/media/admin/'

    you would gived no media. Page on without css, js, images for it way.

    I got it but documentation django recomended like: ADMIN_MEDIA_PREFIX = '/media/admin/'

    Thanks

Post a Comment

Your email is never shared. Required fields are marked *

*
*