Archive for August, 2013

Publishing Data to Redis with Django Signals

Just something I found and thought was kind of cool. I’m currently working on a project that uses Django for its frontend, but eventually passes the user to a JavaScript frontend that talks to the Node.js / Redis backend with Socket.IO. I needed a way to store data in Redis whenever a specific Django model was saved. I looked up ‘Django + redis’ beforehand, but the existing projects seem to be mostly cache-oriented, and as far as I know Django doesn’t have a standard adapter for Redis. No worries — it’s all Python!

Django signals let you execute functions whenever a signal is emitted, but specifically in my case, when a model is saved. You can put your signals code anywhere, but I like to make a ‘signals.py’ in the app directory and then just add the line ‘import signals’ to the app’s __init__.py. I subscribed to the Django model saved and model deleted signals with functions that connect to Redis and add some of the relevant data to a hash. Hashes in Redis are very much like dicts in Python, and Andy McCurdy’s redis-py library allows you to pass dicts directly to the hmset function.

Here’s the relevant code (adapted for the example) in signals.py:

import redis
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from yourapp.models import YourModel

@receiver(post_save, sender=YourModel, dispatch_uid="yourmodel_create")
def addYourModelToRedis(sender, instance, **kwargs):
	r = redis.StrictRedis(host='localhost', port=6379, db=0)
	yourmodel_dict = {
		'uid': instance.user.id,
		'number1': instance.number_1,
		'number2': instance.number_2,
		'status': instance.status
	}
	r.hmset('yourmodel:' + instance.uniqueKey, yourmodel_dict)

@receiver(post_delete, sender=YourModel, dispatch_uid="yourmodel_delete")
def removeYourModelFromRedis(sender, instance, **kwargs):
	r = redis.StrictRedis(host='localhost', port=6379, db=0)
	r.delete('yourmodel:' + instance.uniqueKey)

The “dispatch_uid” parameter passed to the receiver decorator is intended to keep the signal from being acted upon more than once per save/deletion of a model. All the Django documentation says is to use a unique string; they don’t recommend that you use a specific format and it doesn’t seem to matter as long as it’s unique. Another thing to note is that the ‘instance’ parameter for my handler functions is specific to the post_save and post_delete signals. In general signal handlers are expected to take “sender” and “**kwargs.” However it’s safe to extract the ‘instance’ variable from **kwargs in the function definition when only being used for these specific signals. More information about signals and handling signals can be found in the Django documentation.