Development Client Admin for Django

Development

Client Admin for Django

Concentric Sky recently open sourced version 1.0 of Client Admin, the Django admin interface we use as a basis for most of the Django projects we're involved in. I'm going to review a bit of background on the built-in Django admin interface, then talk about what we've done with Client Admin and where we'd like to take it in the future.

One Person's CRUD is Another's Treasure

Many developers use Django because it includes an out-of-the-box admin interface, contrib.admin, that provides basic functions to create, read, update and delete (CRUD) your data. Orginally designed by Wilson Miner, it provided a great way to manage data using the power and structure of Django's ORM. I say 'provided' in the past tense not because it is now gone, but because users' expectations have evolved as the interfaces of competing web frameworks have become more polished.
 
As good as Miner's design was in 2005, it now feels stale. It doesn't have a responsive layout or JQuery UI widgets or AJAX. It is difficult to add the functionality that many of our clients expect. And incrementally improving the interface has been slow for several reasons:
  • First, contrib.admin is bundled with Django core, so updates are limited to major releases. This wouldn't be a problem in the long run as new features would eventually make it in, but updates to the admin are understandably prioritized below security fixes or new features.
  • Second, few designers want to touch Wilson Miner's work. He would agree with many of the updates being discussed, but I can understand why professional designers don't want to set themselves up for that sort of scrutiny for unpaid open-source work.
  • Third, it is such a daunting project that most developers that have the need for something beyond contrib.admin end up building something on their own and branding it as something separate - like Django CMS or Mezzanine. In theory, some features from libraries like Django Admin Tools or Grappelli could be merged into contrib.admin, but I haven't seen much discussion of that from those libraries' maintainers or the core Django developers.
Here at Concentric Sky, we've decided to provide extra functionality to clients by extending the existing contrib.admin. We didn't want a full CMS that takes control of URL structure, so using something like Django CMS was out of the question. We borrowed some features from the Django Admin Tools package, and added custom widgets, views, and an entirely new skin. As you can imagine, our strategy of piggy-backing on contrib.admin has many pros and cons. We automatically get most features and bug fixes introduced in newer versions of Django. We can still use contrib.admin's class definitions for registering apps with the interface and third-party apps that register themselves still work. But we are starting to hit the limit of what we can patch on top and are being held back by the legacy codebase. 
 
So what is the future of contrib.admin? Is some core developer going to eventually add modern features? Idan Gazit is Django's Benevolent Designer For Life, so he would have the last say. But I don't think he has the time to actually implement any grand plans. What is far more likely is that some package emerges as a great replacement and eventually gets adopted into Django.
 
As Russell Keith-Magee, another core developer, says:
 
"Admin is a contrib app for a reason -- it's a standalone app. It's entirely possible to recreate everything Django's admin does as a third party application. If a third party admin implementation were to appear that had a better feature set than the existing admin, and/or a better codebase to start from, and there was a reasonable migration path from old admin configurations to new admin configurations, *that* might be a viable way to get a new admin into Django.
 
However, all of this is dependent on someone having enough of an itch, and enough spare time to scratch it."
 
We feel like we have both the itch and the ability, but getting a rewrite into core is not our primary goal. Like Keith-Magee and Gazit have mentioned several times on Django's Google Groups, nothing is preventing us from having a successful third-party admin app that provides everything we and our clients need in an admin interface.
 

The Current State of Affairs

Here are the major features that Client Admin currently gives you by default:
 
Of course, it provides new styles. There are now myriad Bootstrap themes for contrib.admin that overlap many of our design goals, but we wanted something that closely matches our company's branding.
 
 
Client Admin provides a dashboard with draggable widgets, a menu persistent on all admin pages, and a system of admin bookmarks that allow users to save favorite pages and have them available from the menu. All three of these features are originally from Django Admin Tools.
 
It also provides a ClientModelAdmin class that improves default widgets and settings over the default admin.ModelAdmin class. This maintains contrib.admin's ability to register models with one line of code.
 
Along with that general admin class, Client Admin provides an additional inline type, Grouped, that acts much like a Stacked inline but floats each field group instead of clearing them. This allows for a much more condensed layout when an inline form has just one or two fields.
 

 

Portmanteaued Glue

Jingo, Djanjinja, Djinja, ... Coffin. Are you one of the many Django developers that use Jinja2 templates (and one of the ridiculously named adapter libraries) instead of the built-in system? Do you also wish you could share base templates between your admin backend and your front-end site? I wrote up a detailed description of how to do that back in January.
 
Client Admin implements this solution and uses Jinja2 templates for the base template that includes the header menu. Assuming certain blocks are present in your template, this means the admin interface could also inherit branded headers and footers from front-end templates that were written in Jinja2. This feature will probably be pulled out into a separate library at some point, and will eventually be unnecessary if Client Admin re-writes all of contrib.admin's templates instead of inheriting from them. But Django has no plans to officially adopt the Jinja2 template system, and that would mean something must give if Client Admin code is ever expected to become part of contrib
 

Bonus Features

Here are some additional features provided by registering with (or inheriting from) the ClientModelAdmin class:
 
It provides nested inline formsets for ModelAdmin classes. This really only works when nesting an inline inside of a stacked inline, since nesting inside of a tabular inline would mean the second inline would have to fit in a tiny table column.
 
It adds an advanced search form to change list views. It also works with fields on related tables and integrates seamlessly with the existing filters and search form.
 
 
It provides an improved raw-ID foreignkey widget that displays unicode instead of the object's pk.The label is also a link to the detail view of that related object.
 
 
It includes revision history and deleted object recovery via django-reversion. This is an incredibly useful library, and takes very little code to integrate. In fact, simply include 'reversion' in your installed apps, and it will automatically be applied to all admin models using ClientModelAdmin.
 

Into the Future

Our ideas for Client Admin are closely aligned with AdminNext, a wiki page on djangoproject.com. We've already developed some of the features, but here are the most important ones that remain:
 
  • This project is currently tested against Django 1.5 and 1.6. If this project is useful to other developers, then compatibility with older or newer versions could be tested and verified.
  • A full template rewrite with responsive HTML would make the interface device-independent.
  • Providing clear patterns to extend the admin would be much easier if the views were re-written as class-based views. We could perhaps start with the work of Julien Phalip.
  • Abstracting the list views as generic table views of models would be great, and we could possibly use the django-tables2 codebase.
  • We have done some work on reverse inlines, which allows for inlining a form for an object referenced from the current form. Currently, creating objects in this pattern involves a raw ID widget and a separate popup window. But the current inline formset factory can be cloned to handle an object your form is dependent on, instead of an object that is dependent on your form.
A complete break from contrib.admin would be necessary to move forward on some of these tasks. We will continue to improve this library, but getting it out into the public will allow us to hear much-needed feedback, especially as we begin to tackle some of these larger changes. And hopefully other developers will find this library as useful as we do. Please fork it on Github, provide feedback in the issues queue, and make pull requests if you've made improvements for the better.

comments powered by Disqus