I'm running a gevent-socketio Django application.
I have something similar to this class
@namespace('/connect')
class ConnectNamespace(BaseNamespace):
def on_send(self, data):
# ...
However, if I receive the events from the javascript client, everything works and for instance send
event is processed correctly
I'm a little bit lost if I want to emit
some event on the server side. I can do it inside the class with socket.send_packet
But now I want to link some event to post_save
signal, so I'd like to send_packet
from outside this namespace class, one way of doing this would be
ConnectNamespaceInstance.on_third_event('someeventname')
I just can't figure out how can I get the instance of ConnectNamespaceInstance
To sum it up, I just want to send an event to javascript client after I receive post_save
signal
What you probably want to do is add a module variable to track connections, say _connections
, like so:
_connections = {}
@namespace('/connect')
class ConnectNamespace(BaseNamespace):
and then add initialize
and disconnect
methods that use some happy identifier you can reference later:
def initialize(self, *args, **kwargs):
_connections[id(self)] = self
super(ConnectNamespace, self).initialize(*args, **kwargs)
def disconnect(self, *args, **kwargs):
del _connections[id(self)]
super(ConnectNamespace, self).disconnect(*args, **kwargs)
When you need to generate an event, you can then just look up the right connection in the _connections
variable, and fire off the event with emit
.
(Didn't test any of this, but I've used a similar pattern in many other languages: don't see any reason why this wouldn't work in Python as well).
Other then Femi's answer, which I think certainly works. Using Redis would probably give you a bit more flexibility and using greenlet from gevent may qualify this approach as a bit more "in the framework", since you are already using gevent-socketio :D
REDIS_HOST = getattr(settings, 'REDIS_HOST', '127.0.0.1')
class YourNamespace(BaseNamespace):
def _listener(self, channel_label_you_later_call_in_post_save):
pubsub = redis.StrictRedis(REDIS_HOST).pubsub()
pubsub.subscribe(chan)
while True:
for i in pubsub.listen():
self.send({'message_data': i}, json=True)
def recv_message(self, message):
if is_message_to_subscribe(message):
self.spawn(self.listener, get_your_channel_label(message))
And in your post_save, you can do
red = redis.StrictRedis(REDIS_HOST)
red.publish(channel_label, message_data)