30 August 2009

Cool tricks with the Django admin interface

At work we've been doing lots with the Django toolkit. One of the things we've been looking at lately is whether we can (without overriding lots of code) have a different admin interface for inserting an object versus updating an object. The answer: yes, trivially.

I don't have space for a full Django tutorial here, so I'll assume you know all the Django lingo. This example assumes you have a project set up, and within that you have an application called AssetVersions, and within that you have a class called Asset (all of which, I have, in fact). What if you wanted the insert interface to have the field 'name' and 'project', but wanted the update interface to have all fields except 'project'? (this makes 'project' an insert-time-only property).

  • In your admin.py for AssetVersions, create a separate AdminModel class for Asset, and add it to a separate instance of the AdminSite class. We'll stick that instance on admin.create_site for convenience:

    import models
    from django.contrib import admin
    from django import forms

    class AssetAdmin(admin.ModelAdmin):
    exclude = ( 'project', )
    admin.site.register(models.Asset,AssetAdmin)

    admin.create_site = admin.AdminSite()

    class AssetAdmin(admin.ModelAdmin):
    fields = ( 'name', 'project', )
    admin.create_site.register(models.Asset,AssetAdmin)

  • Then, in the urls.py for your project, override the url for the specific application and Model class to access the alternate AdminSite:

    from django.conf.urls.defaults import *
    from django.contrib import admin
    admin.autodiscover()


    urlpatterns = patterns('',
    (r'^', include('AssetVersions.urls')),
    url(r'^admin/(AssetVersions/asset/add/)', admin.create_site.root),
    url(r'^admin/(.*)', admin.site.root),
    )



Voila, the create and edit interfaces are now decoupled, and yet each AdminSite is pretty much largely ignorant of the other.

No comments: