Growl type notifications in Django

First, a little background

Django has an excellent messages framework which provides support for cookie and session-based messaging, for both anonymous and authenticated users.

The messages framework allows you to temporarily store messages in one request, and retrieve them for display in a subsequent request (usually the next one). Every message is tagged with a specific level determining its priority (e.g. success, info, error).

For example, in a view you can send a message:

from django.contrib import messages
messages.success(request, "Profile details updated.")

Then in the template you can display it, for example:

{% for message in messages %}
    <li class="{{ message.tags }}">{{ message }}</li>
{% endfor %}

The Django admin interface displays messages in bar type fashion. I liked this implementation and copied it for the TurnKey Hub, with the added visual tweak of fading out the message bar after timeout (or when clicked).

It's simple, minimal, and has worked well until now. But our needs are changing as the Hub is evolving. We need more flexibility and power.

Our current implementation falls short in the following:

  • Messages can't be specified as sticky (so they don't auto-close).
  • Can't be programmatically created and closed for use via AJAX.
  • Moves the whole page down, then up again (a little annoying).
  • Limited space for the message text.
  • They don't stack well (multiple messages).
  • And finally, they look OK, but we can do better...

Growl type notifications

As far as I know, Growl first appeared in Max OS X as a global notification system allowing applications to display small notifications about events to the user in a consistent manner.

Ubuntu then created their own implementation deemed Notifications, indicators and alerts for 9.04. It's useful and looks great, and I wanted to have something similar in the Hub.

It turns out that Eric Hynds did some great work on this exact topic (see the demo), which made it super simple for us to transition over to growl type notifications and solve all our issues with the current implementation.

With a couple of template tags and tweaks here and there, we can now send regular notification that auto-expire, are sticky so the user needs to take action, as well as super sticky where the user can't close the notification.

Auto expire vs. sticky notification

You might be wondering how we differentiate between regular auto-expiring and sticky notifications. It's actually quite simple.

The Django messages framework allows extra adhoc tags to be specified when creating the message, for example:

from django.contrib import messages
messages.success(request, "Profile details updated.", extra_tags="sticky")

A custom template tag filter will parse the tags, and set the notification expire argument accordingly.

Another bonus was a minor tweak to notify.js to automatically hide the close-link 'x' on expiring notifications, indicating to the user that no action is needed.

An example of super sticky notifications vs. our old implementation

One of the services provided by the Hub is the front-end interface to TurnKey Backup and Migration (TKLBAM) - the easiest, most powerful automated backup/restore system. Ever.

It provides efficient system-level backups that can be restored automatically on any installation of the same virtual appliance, regardless of the underlying hardware or location.

Anyway, TKLBAM's default storage backend is Amazon S3, providing ultra-durable encrypted cloud storage. When enabling TKLBAM's cloud storage on Amazon, there is sometimes an unspecified delay until Amazon verify the users payment details. For this we execute a background task polling Amazon's licensing API.

While the task is running, we use AJAX to check the status of the task and update the user accordingly.

Our old implementation was to hide/show pre-configured div's (acting as poorman notifications). It worked, but it's a complex kludge and doesn't provide a unified user-experience.

We replaced this kludge by programmically creating a super sticky notification (which the user cannot close), and when Amazon complete their vetting process, a successful notification is displayed and the super sticky notification is closed.

Note: the new notification code will be pushed to production when the Hub is taken out of beta (really really soon!)