[Fixed]-Django: JSON Notifications using Redis PubSub, Node.js & Socket.io

3👍

I’d definitely not use node.js for this. You can handle websockets in Python just fine, with Celery or gevent or whatever.

Just create a thread which registers to Redis and listens for new messages.

When the user connects, put the socket into a weak-value hash indexed by the user’s name; when a message for them arrives, look up the destination username in that hash and send it off. Weak-value because it cleans up after itself when the user disconnects. Simple, really.

I’d also send new messages to the server using the websocket instead of HTTP-PUT.

2👍

👤djvine

1👍

Sounds like you should use something like RabbitMQ http://www.rabbitmq.com/devtools.html there’s a node.js implementation and more.

Check it out, it should cheer you up 🙂

0👍

I’m also using a wonderful library called django-websocket-redis.

Although it doesn’t use gunicorn, it uses uWSGI, which shouldn’t have too much overhead in migrating to. Just follow the docs, they’re quite comprehensive.

https://django-websocket-redis.readthedocs.org/en/latest/

Taking some of your code and implementing it with django-websockets-redis:

## Make a json representation of your model available.

class Comment(models.Model):
     comment = models.CharField(max_length=140)
     user = models.ForeignKey(User)
     post_id = models.ForeignKey(Post)
     created_at = models.DateTimeField(auto_now_add=True)

    def as_json(self):
        return dict(
        id=self.id,
        comment=self.comment,
        created_at=self.created_at.strftime('%m/%d/%Y'),
        post_id=self.post_id
        user=self.user
        )

Then, in your views, when making the request, save a json representation to the redis facility you’re subscribed to…you can do this anywhere really, either your serializer or view, but i’l leave that up to you.

def UploadComment(request):
     data  = json.loads(request.body)

     ## In django-websockets-redis, this portion below is registered in the settings.py file, therefore i am commenting this out. 
     ## redis_server = redis.Redis(host='12.345.678.9', port=6379, db=0, password='mypassword')

     newComment = Comment()
     newComment.comment = data['comment']
     newComment.user_id = data['user_id']
     newComment.post_id = data['post_id']
     newComment.save() 
     PostOwner = data['post_owner_id'] #id of the blog post owner
     # Need to send a notification to PostOwner

     ## Need to turn this into a string before posting to redis
     json_comment = str(newComment.as_json())

     ## Create a facility based on the PostOwner ID. The PostOwner will always be subscribed to this channel. 
     RedisPublisher(facility=PostOwner, broadcast=True).publish_message(json_comment)

     return HttpResponse('Request Successful')

Now that we’ve got the backend taken care of, on the front end visa vie JavaScript, your user subcribes to the Facility based on his user.id:

jQuery(document).ready(function($) {
    var ws4redis = WS4Redis({
    uri: '{{ WEBSOCKET_URI }}{{ PostOwner.id }}?subscribe-broadcast&publish-broadcast&echo',
    receive_message: receiveMessage,
    heartbeat_msg: {{ WS4REDIS_HEARTBEAT }}
});

// receive a message though the Websocket from the server
function receiveMessage(msg) {
    //This is where you would retrieve the JSON string from the Redis server, and subsequently manipulate the DOM with appends, Toastr Notifications, Etc...
}

Leave a comment