django - signals
continuing the recent thread about content types in django I thought I would talk about a feature which got added in the magic removal branch, which doesn't have as much attention as I think it deserves. signals and the dispatcher. signals are way of telling the rest of the world that something happened. If you are interested you simply listen for it (connect in django speak). take for example my "tagging application":http://svn.zyons.python-hosting.com/trunk/zilbo/common/tag/ currently in use on "zyons":http://zyons.com. one of it's features is that it let's users store their own tags. One of the performance improvements I added to this was the creation of a 'summary' tag which aggregates which the users preferences into a single record. Now, the first approach I could have taken was to call a 'generate_summary_tag' function every time I modify the user tag, but that was just messy, and it would be quite possible that I would forget somewhere. Instead I did the following in the models.py:
dispatcher.connect( increment_tag_summary , signal=signals.pre_save, sender=TagUserObject )
dispatcher.connect( decrement_tag_summary , signal=signals.post_delete, sender=TagUserObject )
Now.. every time the django ORM updates a TagUserObject record my function will get called. Other examples in the "zyons":http://zyons.com code base include using signals to update the forum and conversation models to show the last-comment date and the number of posts. (instead of looking them up). But you don't need to only use django's pre-defined signals. you can create your own. For example, in my "counter":http://svn.zyons.python-hosting.com/trunk/zilbo/common/counter/ application (which is used to determine 'popular' conversations in the forums) uses a custom signal (object_viewed) to do it's work. Whenever a user views a forum or a conversation a object_view signal is sent. ala
dispatcher.send(signal=signals.object_viewed, request=request, object = object )
At the moment I'm doing the heavy lifting at request time, but there is nothing stopping me just changing the logic of 'increment_tag_summary' to use "ActiveMQ":http://incubator.apache.org/activemq/ via "Stomp":http://stomp.codehaus.org/ and having a seperate batch job do it instead. Other uses of the pre_save signal that I plan to do in the near future is to update a "SolR":http://incubator.apache.org/solr/ lucene-based search server and use it instead of some complex/heavy MySQL that is currently done, by creating a 'de-normalised' version of some of the records and sticking it in SolR. Oh... and a request.. zyons.com is looking for a new home. If you can provide a mod-python,