2013-03-20 13 views
19

Używam aplikacji Django do gevent-socketio.Jak emitować zdarzenie SocketIO na serwerze

Mam coś podobnego do tej klasy

@namespace('/connect') 
class ConnectNamespace(BaseNamespace): 

    def on_send(self, data): 
     # ... 

Jednak jeśli otrzymam wydarzenia od klienta JavaScript, wszystko działa i na przykład send zdarzenie jest przetwarzane prawidłowo

jestem trochę utracone, jeśli chcę emit jakieś wydarzenie po stronie serwera. Mogę to zrobić wewnątrz klasy z socket.send_packet

Ale teraz chcę połączyć jakieś zdarzenie post_save sygnału, więc chciałbym send_packet spoza tej klasie przestrzeni nazw, jednym ze sposobów na osiągnięcie tego byłoby

ConnectNamespaceInstance.on_third_event('someeventname') 

po prostu nie może dowiedzieć się, w jaki sposób mogę uzyskać wystąpienie ConnectNamespaceInstance

Podsumowując, chcę wysłać do klienta zdarzenia javascript po otrzymaniu post_save sygnału

+0

http://stackoverflow.com/questions/13504320/socket-io-namespaces-channels-co – catherine

+2

mam ten sam problem, i nie można rozwiązać ... jakiś pomysł? – jetmc

+0

Przykro mi, ale nie sądzę, że sugerowano duplikowanie odpowiedzi na moje pytanie: –

Odpowiedz

7

Co prawdopodobnie chcesz zrobić, to dodać zmienną moduł śledzenia połączeń powiedzieć _connections, tak:

_connections = {} 

@namespace('/connect') 
class ConnectNamespace(BaseNamespace): 

a następnie dodać initialize i disconnect metod, które używają jakiś szczęśliwy identyfikator można odwoływać później:

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) 

Gdy potrzebujesz wygenerować zdarzenie, możesz po prostu wyszukać właściwe połączenie w zmiennej _connections i wystrzelić zdarzenie z emit.

(Nie przetestowałem żadnej z tych opcji, ale użyłem podobnego wzorca w wielu innych językach: nie widzę żadnego powodu, dla którego nie byłoby to również możliwe w Pythonie).

+1

Zastanawiam się, czy istnieje pewne wbudowane narzędzie do robienia tego w ramach, ale jest to naprawdę miłe obejście, o którym powinienem pomyśleć! +1 :) dziękuję –

+0

każdy przykład transmisji do kanału z tym rozwiązaniem? –

+1

Pomogło mi to wysyłać wiadomości na sygnał post_save w Django. Naprawdę fajne rozwiązanie. – kpacn

0

Inne niż odpowiedź Femi, która moim zdaniem na pewno działa. Korzystanie Redis prawdopodobnie daje nieco większą elastyczność i używając Greenlet z gevent mogą kwalifikować tego podejścia jako nieco bardziej „w ramach”, ponieważ już używasz 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)) 

I w post_save można zrobić

red = redis.StrictRedis(REDIS_HOST) 
red.publish(channel_label, message_data)