Django has come a long way with the 1.3 release, and one of things that developers aren't taking advantage of as much as they should is Signals.
Signals in Django are similar to other event based frameworks, such as Backbone.js.
By using a pubsub event model, you can keep application logic centralized and decoupled from other parts of the code. An example of this is letting an application know when it should clear cached data.
Let's say we have a blog that provides an RSS feed of all the recent posts, using Django's Syndication module.
We want to cache the database call used to retrieve the most recent posts so that we happily scale as more people subscribe to our feed.
from django.core.cache import cache
from blog.models import BlogPost
def items(self):
posts = cache.get('feed')
if posts is None:
posts = BlogPost.objects.all().order_by('-published_on')[:10]
cache.set('feed', posts, 86400)
return articles
How do we easily expire the cached data when we publish a new post?
Without using signals we'd have to clear the cache from within the code that saves and publishes new blog posts. This seems a bit backwards, since the feed should be able to clear its own cache.
By adding a receiver (i.e. listener) to our feed, we can have the feed clear its cache after a BlogPost instance is saved to the database.
from django.db.models.signals import post_save
@receiver(post_save, sender=BlogPost)
def clear_cache(sender, instance, created, **kwargs):
if instance.published_on is not None:
cache.delete('feed')
This code is doing several things here:
What would trigger our receiver is something like this:
post = BlogPost()
post.content = 'My great blog post.'
post.published_on = datetime.now()
post.save()
Now our cached RSS feed will always be up to date with the most recent blog posts, and our BlogPost model is free of having to know about the RSS feed at all. This clean separation of code makes our Django application easier test and maintain.