From 4074cf827260557216993d3320ec8ad41226e0be Mon Sep 17 00:00:00 2001 From: sillygod Date: Tue, 28 Jun 2016 21:31:25 +0800 Subject: [PATCH 1/2] add django example for python-socketio --- examples/django_chat/chat/__init__.py | 0 examples/django_chat/chat/admin.py | 3 + .../django_chat/chat/management/__init__.py | 0 .../chat/management/commands/__init__.py | 0 .../management/commands/runserver_socketio.py | 108 ++++++++++++++++++ .../django_chat/chat/migrations/__init__.py | 0 examples/django_chat/chat/models.py | 3 + examples/django_chat/chat/sockets.py | 64 +++++++++++ examples/django_chat/chat/templates/base.html | 91 +++++++++++++++ examples/django_chat/chat/tests.py | 3 + examples/django_chat/chat/urls.py | 13 +++ examples/django_chat/chat/views.py | 6 + examples/django_chat/db.sqlite3 | Bin 0 -> 36864 bytes examples/django_chat/django_chat/__init__.py | 0 examples/django_chat/django_chat/settings.py | 105 +++++++++++++++++ examples/django_chat/django_chat/urls.py | 11 ++ examples/django_chat/django_chat/wsgi.py | 16 +++ examples/django_chat/manage.py | 10 ++ examples/django_chat/readme.md | 18 +++ examples/django_chat/requirement.txt | 3 + examples/django_chat/sdjango/__init__.py | 103 +++++++++++++++++ examples/django_chat/sdjango/sd_manager.py | 22 ++++ examples/django_chat/sdjango/sd_middleware.py | 64 +++++++++++ examples/{ => flask_chat}/README.rst | 0 examples/{ => flask_chat}/app.py | 0 examples/{ => flask_chat}/latency.py | 0 examples/{ => flask_chat}/requirements.txt | 0 examples/{ => flask_chat}/static/style.css | 0 .../{ => flask_chat}/templates/index.html | 0 .../{ => flask_chat}/templates/latency.html | 0 30 files changed, 643 insertions(+) create mode 100644 examples/django_chat/chat/__init__.py create mode 100644 examples/django_chat/chat/admin.py create mode 100644 examples/django_chat/chat/management/__init__.py create mode 100644 examples/django_chat/chat/management/commands/__init__.py create mode 100644 examples/django_chat/chat/management/commands/runserver_socketio.py create mode 100644 examples/django_chat/chat/migrations/__init__.py create mode 100644 examples/django_chat/chat/models.py create mode 100644 examples/django_chat/chat/sockets.py create mode 100644 examples/django_chat/chat/templates/base.html create mode 100644 examples/django_chat/chat/tests.py create mode 100644 examples/django_chat/chat/urls.py create mode 100644 examples/django_chat/chat/views.py create mode 100644 examples/django_chat/db.sqlite3 create mode 100644 examples/django_chat/django_chat/__init__.py create mode 100644 examples/django_chat/django_chat/settings.py create mode 100644 examples/django_chat/django_chat/urls.py create mode 100644 examples/django_chat/django_chat/wsgi.py create mode 100755 examples/django_chat/manage.py create mode 100644 examples/django_chat/readme.md create mode 100644 examples/django_chat/requirement.txt create mode 100644 examples/django_chat/sdjango/__init__.py create mode 100644 examples/django_chat/sdjango/sd_manager.py create mode 100644 examples/django_chat/sdjango/sd_middleware.py rename examples/{ => flask_chat}/README.rst (100%) rename examples/{ => flask_chat}/app.py (100%) rename examples/{ => flask_chat}/latency.py (100%) rename examples/{ => flask_chat}/requirements.txt (100%) rename examples/{ => flask_chat}/static/style.css (100%) rename examples/{ => flask_chat}/templates/index.html (100%) rename examples/{ => flask_chat}/templates/latency.html (100%) diff --git a/examples/django_chat/chat/__init__.py b/examples/django_chat/chat/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/django_chat/chat/admin.py b/examples/django_chat/chat/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/examples/django_chat/chat/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/examples/django_chat/chat/management/__init__.py b/examples/django_chat/chat/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/django_chat/chat/management/commands/__init__.py b/examples/django_chat/chat/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/django_chat/chat/management/commands/runserver_socketio.py b/examples/django_chat/chat/management/commands/runserver_socketio.py new file mode 100644 index 0000000..55a0a98 --- /dev/null +++ b/examples/django_chat/chat/management/commands/runserver_socketio.py @@ -0,0 +1,108 @@ +from re import match +from _thread import start_new_thread +from time import sleep +from os import getpid, kill, environ +from signal import SIGINT +import six +import copy + +from django.conf import settings +from django.core.handlers.wsgi import WSGIHandler +from django.core.management.base import BaseCommand, CommandError +from django.core.management.commands.runserver import naiveip_re, DEFAULT_PORT +from django.utils.autoreload import code_changed, restart_with_reloader +from django.core.wsgi import get_wsgi_application + +# from gevent import pywsgi +from sdjango import autodiscover +from sdjango import namespace +from sdjango.sd_manager import SdManager +from sdjango.sd_middleware import SdMiddleware +import socketio +import eventlet + + +RELOAD = False + +def reload_watcher(): + global RELOAD + while True: + RELOAD = code_changed() + if RELOAD: + kill(getpid(), SIGINT) + restart_with_reloader() + sleep(1) + +class Command(BaseCommand): + + def add_arguments(self, parser): + parser.add_argument('addrport', nargs='?', help='Optional port number, or ipaddr:port') + + def handle(self, *args, **options): + from django.utils import translation + from django.conf import settings + + translation.activate(settings.LANGUAGE_CODE) + addrport = options.get('addrport', None) + if addrport is None: + self.addr = '' + self.port = DEFAULT_PORT + else: + m = match(naiveip_re, addrport) + if m is None: + raise CommandError('"%s" is not a valid port number ' + 'or address:port pair.' % options['addrport']) + self.addr, _ipv4, ipv6, _fqdn, self.port = m.groups() + + if not self.port.isdigit(): + raise CommandError('"%s" is not a valid port number' % self.port) + + if not self.addr: + self.addr = '127.0.0.1' + # Make the port available here for the path: + # socketio_tags.socketio -> + # socketio_scripts.html -> + # io.Socket JS constructor + # allowing the port to be set as the client-side default there. + environ["DJANGO_SOCKETIO_PORT"] = str(self.port) + + if settings.DEBUG is True: + start_new_thread(reload_watcher, ()) + + try: + bind = (self.addr, int(self.port)) + print("SocketIOServer running on %s:%s" % bind) + handler = self.get_handler(*args, **options) + + # sio = socketio.Server(client_manager=SdManager(), async_mode='gevent') + sio = socketio.Server(client_manager=SdManager(), async_mode='eventlet') + autodiscover() + namespace.insert_in_server(sio) + + app = get_wsgi_application() + app = SdMiddleware(sio, handler) + eventlet.wsgi.server(eventlet.listen(bind), app) + + except KeyboardInterrupt: + # eventlet server will handle exception + # server.stop() + # if RELOAD: + # print("Reloading...") + # restart_with_reloader() + pass + + def get_handler(self, *args, **options): + """ + Returns the django.contrib.staticfiles handler. + """ + handler = WSGIHandler() + try: + from django.contrib.staticfiles.handlers import StaticFilesHandler + except ImportError: + return handler + use_static_handler = options.get('use_static_handler', True) + insecure_serving = options.get('insecure_serving', False) + if (settings.DEBUG and use_static_handler or + (use_static_handler and insecure_serving)): + handler = StaticFilesHandler(handler) + return handler diff --git a/examples/django_chat/chat/migrations/__init__.py b/examples/django_chat/chat/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/django_chat/chat/models.py b/examples/django_chat/chat/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/examples/django_chat/chat/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/examples/django_chat/chat/sockets.py b/examples/django_chat/chat/sockets.py new file mode 100644 index 0000000..664f98c --- /dev/null +++ b/examples/django_chat/chat/sockets.py @@ -0,0 +1,64 @@ +import logging +from sdjango import namespace + + +online_user_num = 0 + + +@namespace('/test') +class TestNamespace: + + def __init__(self, name): + self.name = name + self.request = None # django request object + + def _get_socket(self, sid): + socket = namespace.server.eio._get_socket(sid) + return socket + + def _get_request(self, sid): + socket = self._get_socket(sid) + return socket._request + + def emit(self, *args, **kwargs): + if 'namespace' not in kwargs: + kwargs['namespace'] = self.name + + namespace.server.emit(*args, **kwargs) + + def on_my_event(self, sid, message): + self.emit('my response', {'data': message['data']}, room=sid) + + def on_my_broadcast_event(self, sid, message): + self.emit('my response', {'data': message['data']}) + + def on_join(self, sid, message): + namespace.server.enter_room(sid, message['room'], namespace='/test') + self.emit('my response', {'data': 'Entered room: '+message['room']}, room=sid) + + def on_leave(self, sid, message): + namespace.server.leave_room(sid, message['room'], namespace='/test') + self.emit('my response', {'data': 'Left room:'+message['room']}, room=sid) + + def on_close_room(self, sid, message): + self.emit('my response', {'data': 'Room '+message['room']+ ' is closing'}, + room=message['room']) + namespace.server.close_room(message['room'], namespace='/test') + + def on_my_room_event(self, sid, message): + self.emit('my response', {'data': message['data']}, room=message['room']) + + def on_disconnect_request(self, sid): + namespace.server.disconnect(sid, namespace='/test') + + # two method must have + def on_connect(self, sid, environ): + if 'django_request' in environ: + request = environ['django_request'] + socket = self._get_socket(sid) + socket._request = request + + self.emit('my response', {'data': "{} Connected".format(request.user), "count": 0}, room=sid) + + def on_disconnect(self, sid): + print('Client disconnected') diff --git a/examples/django_chat/chat/templates/base.html b/examples/django_chat/chat/templates/base.html new file mode 100644 index 0000000..19e11b6 --- /dev/null +++ b/examples/django_chat/chat/templates/base.html @@ -0,0 +1,91 @@ + + + + Django-SocketIO Test + + + + + +

Flask-SocketIO Test

+

Send:

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + + +
+
+ + +
+
+ +
+

Receive:

+

+ + diff --git a/examples/django_chat/chat/tests.py b/examples/django_chat/chat/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/examples/django_chat/chat/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/examples/django_chat/chat/urls.py b/examples/django_chat/chat/urls.py new file mode 100644 index 0000000..8afd17e --- /dev/null +++ b/examples/django_chat/chat/urls.py @@ -0,0 +1,13 @@ +from django.conf.urls import ( + url, patterns, include +) + +import sdjango + +from .views import socket_base + + +urlpatterns = [ + url(r'^socket\.io', include(sdjango.urls)), + url(r'^$', socket_base, name='socket_base'), +] diff --git a/examples/django_chat/chat/views.py b/examples/django_chat/chat/views.py new file mode 100644 index 0000000..8e9a471 --- /dev/null +++ b/examples/django_chat/chat/views.py @@ -0,0 +1,6 @@ +from django.shortcuts import render + + +def socket_base(request, template="base.html"): + context={} + return render(request, template, context) diff --git a/examples/django_chat/db.sqlite3 b/examples/django_chat/db.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..f2c4eebc5cb2c7f5cfac9c438a42ba0b0cc438af GIT binary patch literal 36864 zcmeHQeQX>@72ny}yYo455<77>P3m}kjvHSc$9tc?OXQ~4^hn*rPLnu5QlahIUSBS` zuil+wJLM0~jw+x+pdg_Np@KxEA|%9z1pL!Vs0dL}i7)XF2%)M-Z9#m93V{Ut!JFCd z^_`tMZqmqeQN}kjZ{BrHYDYNPfn{! zlV_%+$qT1XOHZB~pU9lMD4oh)lrk5l&Wuk2uZisB)L|)9Qj1zhx~5iVF00kSh%AS# zc2KKUDoR0})(WjjisjigsxM5ApS_R;#cWQ%R&Nsy^DEr(@nVm;Xd>YnmhM68tyL=k z@BR=Z-TNR3?u2C5eUP+m>wvT!eU8IF#b3g+cpv{u{&{|!_o3IIkbUkf0_L4WLb_V`BJ`~R|`=&k{p(k!_lN9r;kPxM`MvA=}0^sl`}yf*FBygvkDp{l`4$& zd{r~8Co!Hi1!|(rSfoZHaXI;D8?ZQKvPdXup{`Yx`5GhzwN_UO;Uh+MJT9Xi}CR7ku2n$&7ImqA(H^0pDWznguVtIVpr` zGo6z0Xet?zv5yl6GU{wGUs~^)CZcIMkr?5j7tlh#rfUuY7y_|KbQFQI172mq&l@=O{-U`rz)3OI(EJlyzq`|uF*JS%l=Z^ON9w2&B8 z{4Tdg&)Ej9o5v$2Kl_QJ9WdS-Y$AqKbm12`{6G9}{2n})zm4C-zr(-5KgX}**YGR& z2lzYqoA@RCA`r0;Lx3T0M-cE~g#2AJ?WE~0lKOVibO%j4NGfcn={B0SlN1MO+D6j= zNqIj_eKZvW97LETJjTHwdH(m~&vN*$__z3HFyFrl8TMfaFa+)}0=xYJ*R$XJ?PvVm z?-RIze&=rx$M@}mz;$<%rvdUX(19T*l3cD@p09NAknJN```Mrq37ptNe}}+NI&iI3 zm&pC!kDur8-|!o7-+vW<4KnP*5MT)0X$1BNJ^PVo{`(&g2Ktd>&et5@eH}t~H~on~ z=D)B*=oV>?&VRgH=ibg!8_h5$q0t|8FDf06TZCpdhN z|25B{H@GiA=EVDo&7Ioj7nO9YxD9nyP>bXU0@aKt(5mu|OsCO}Z8X->ymj-^ z?e3^cbD|A}UUW5^MiS3uKaxF{ojj2}53xab*itC1AtelvJ=^*!x5mJ3U~{p8hL$F) zIETZrpkF-McMI1+kHAq@+Zwyt0%BhuYFzc;ZFi=<6|Nh?(jBQvIijnQ-peq|h2yso zPGs@F!PW7YxR6lvm)Bz4qoDT?sX0YAtC=b{w9C(u9>3^3qHQnFP zbMTXgBz=0C=EqUewY+CXKpY-MD^J-I!BJ1AgCpPBWKuY)H#9Y9`&%;-gw!?J2zRu=ZbP6|)LLz! zT!q1HE!l{sT(NOGgxO>QKyULkr8W;%SI2a^TrODC18PaB+h)a9+bp1)%U2;%+L{tb zs3L1p&^V{vlTmk&pD0>a=jK9^S4pT*XX^QDuyDm&MW(!R1s0IBnEzzPIal>;cm}eD z3;~9~y@mks|FQXhuU$2!FGFB+5Mchl&B2jzVF=ud2(bJAy?E7_&J2OgL4e%sfooi zQy1imS2EGb>p6Mi(`vL_S;*IB@^Ykb zeerUnyeYzE@&ZRJbu^JW5>KY&Wb|1?g(qjLwb(*kF3YK^x|l9#SJjGIzm}>di&u+F zQFZf#!`mbA*paB5NXsd5|Ht?yhi~HF;~(CgOV6Y-1Q-G)0tfK~TF(k%LbRT>;`{ML za6PL+*Z;z6x%?}94n4+wos-ZXO-;z(2G<=Bj}N0pAAJSYis6`nG%YnMN7UK4x8i;y z#xp+oSoY&aXq-lvXl$vbnC(K+naS1FBoaiaAsQBL9M}^OPo+^KYpb9~sO(UAO-aQ@ zW7CmQM{L`<-e7MNbz1XqD7A`+sAkJ0G5v7k{@uEQ$JSC%*3z-G8lR&`tzs+Ql7c3W z^%T_E6Wz!qMEB{Ju-{hCc_~b$-b=WziAv4dIh1i!6P#={&UgC7TxR_+B4uF1>k8C* z>-H>Xb_K*t2Hogz2O9M^7ad&eo_TrfHu`A1L*ANjL$OIJZ9@TFTlvjcHDc-kF-SM# zaG3f3oYszgX9#R91epJCYh7>FTZVuW0e1g)qQSm11hy6e?Eb&Ct~cu~L%@jux&I4X znZplW8GCCKTj?8!~dfmP#Z?)A< z_eFWDiSx#IZ&Kf{iFn3V4&6@|{6B}N_sHAEn?K<86nU#RWMxT;m)B>;2TJ8b6UTJ~-*pDU=jkW?$Gg#v7YD9x8@`5deT zcP?>gG(M1`1C4x9FboNUIWG_YM3kC)%&ISfBfm>GCs>ncNlAwUpd^Pi0a zhQQWEfX)A{d+k}z83JtnvoXLB*t!UGpfc?LHOBGp@d5NBZVWZ>5?X47$MVBcKujdi zjb7?AUmk%hoV9YJ+g^ZayF#f?)6Rz64s>rVcu||Klw9km9;csq{dJOSJEv#h)E@WV zEZ(Dk+_j!PmaJ`bygE_;xxqRd#`9d)Qwg#T*56Og=Ha-pzS}uGr$5`fDTn4XE+5d3 z2U>6jL!5nSg5C#o0F!+%k`>$VUW(f}VyVIHcdlsn26C*G>E4PywplU9xpfL%)h70xS4*RHesKb?gvVF+wV z1lauFl9!!znjt_DVC#R`Kwt=LT?E+uf9qa*)^mnH2fv^5aW8ZHNBMpXT7-@xiA48gCnyx5lU>s%ncBa)>V3JsDo`PlhQ5%Q^;bIqsZi zZ)&x?#3NUcb$imgY(d&2Tjz~OLLuSHrd_%*h7BtOt{r+_ip8^L&Ob< zcYTcE@0ZRh%5bJDZF3;~9~7D0gg{_jG^IoSQ{d-&7%X&l7@|2F>`|02K4Kg~bP z??!K-@1oD691yXO7l8-6d>jf#{Igm?gL4*)TjvS2B7 z(De`b)!A7mGsv10BRhd2a?EE)Gy*#0czTCaqf{crBRlj4hGi%lNh)op>I#N3= 1.9 + from django.utils.module_loading import import_module +except ImportError: + # Django version < 1.9 + from django.utils.importlib import import_module + +from django.conf.urls import patterns, url, include + + +LOADING_SOCKETIO = False + +def autodiscover(): + """ + Auto-discover INSTALLED_APPS sockets.py modules and fail silently when + not present. NOTE: socketio_autodiscover was inspired/copied from + django.contrib.admin autodiscover + """ + global LOADING_SOCKETIO + if LOADING_SOCKETIO: + return + LOADING_SOCKETIO = True + + import imp + from django.conf import settings + + for app in settings.INSTALLED_APPS: + + try: + app_path = import_module(app).__path__ + except AttributeError: + continue + + try: + imp.find_module('sockets', app_path) + except ImportError: + continue + + import_module("%s.sockets" % app) + + LOADING_SOCKETIO = False + + +class namespace: + + """This is a event handler keeper for socketio event + + used as a decorators + """ + + handler_container = {} + server = None + + def __init__(self, name=''): + if not name.startswith('/'): + self.name = '/'+name + self.name = name + + def __call__(self, handler): + instance = handler(self.name) + + if self.name not in namespace.handler_container: + namespace.handler_container[self.name] = [] + + methods = inspect.getmembers(instance, predicate=inspect.ismethod) + + for key, value in methods: + if key.startswith('on_'): + namespace.handler_container[self.name].append(value) + + return True + + @classmethod + def insert_in_server(cls, server): + """a special method to dynamic add event for socketio server + """ + namespace.server = server + + for name, handlers in namespace.handler_container.items(): + + for obj in handlers: + event_name = obj.__name__.replace('on_', '').replace('_', ' ') + server.on(event_name, obj, name) + + namespace.handler_container = {} # reset to empty dict + + +@csrf_exempt +def socketio(request): + try: + request.environ['django_request'] = request + except: + logging.getLogger("socketio").error("Exception while handling socketio connection", exc_info=True) + return HttpResponse(200) + +urls = patterns("", (r'', socketio)) diff --git a/examples/django_chat/sdjango/sd_manager.py b/examples/django_chat/sdjango/sd_manager.py new file mode 100644 index 0000000..0e8bf86 --- /dev/null +++ b/examples/django_chat/sdjango/sd_manager.py @@ -0,0 +1,22 @@ +from socketio.base_manager import BaseManager + + +class SdManager(BaseManager): + + """ + """ + + def initialize(self, server): + # import pdb; pdb.set_trace() + super().initialize(server) + + def connect(self, sid, namespace): + """Register a client connection to a namespace. + and set the django request object? + """ + # TODO: process user authentication here? + # if 'django_request' in self.server.environ[sid]: + # print(self.server.environ[sid]['django_request'].user) + + self.enter_room(sid, namespace, None) + self.enter_room(sid, namespace, sid) diff --git a/examples/django_chat/sdjango/sd_middleware.py b/examples/django_chat/sdjango/sd_middleware.py new file mode 100644 index 0000000..1ab446e --- /dev/null +++ b/examples/django_chat/sdjango/sd_middleware.py @@ -0,0 +1,64 @@ +import urllib +import engineio + + +class SdMiddleware(engineio.Middleware): + """WSGI middleware for Socket.IO. + + This middleware dispatches traffic to a Socket.IO application, and + optionally forwards regular HTTP traffic to a WSGI application. + + :param socketio_app: The Socket.IO server. + :param wsgi_app: The WSGI app that receives all other traffic. + :param socketio_path: The endpoint where the Socket.IO application should + be installed. The default value is appropriate for + most cases. + + Example usage:: + + import socketio + import eventlet + from . import wsgi_app + + sio = socketio.Server() + app = socketio.Middleware(sio, wsgi_app) + eventlet.wsgi.server(eventlet.listen(('', 8000)), app) + """ + def __init__(self, socketio_app, wsgi_app=None, socketio_path='socket.io'): + super().__init__(socketio_app, wsgi_app, socketio_path) + + def __call__(self, environ, start_response): + if 'gunicorn.socket' in environ: + # gunicorn saves the socket under environ['gunicorn.socket'], while + # eventlet saves it under environ['eventlet.input']. Eventlet also + # stores the socket inside a wrapper class, while gunicon writes it + # directly into the environment. To give eventlet's WebSocket + # module access to this socket when running under gunicorn, here we + # copy the socket to the eventlet format. + class Input(object): + def __init__(self, socket): + self.socket = socket + + def get_socket(self): + return self.socket + + environ['eventlet.input'] = Input(environ['gunicorn.socket']) + + path = environ['PATH_INFO'] + if path is not None and \ + path.startswith('/{0}/'.format(self.engineio_path)): + + query = urllib.parse.parse_qs(environ.get('QUERY_STRING', '')) + sid = query.get('sid', None) + + if sid is None: + self.wsgi_app(environ, start_response) + + engineio_res = self.engineio_app.handle_request(environ, start_response) + return engineio_res + + elif self.wsgi_app is not None: + return self.wsgi_app(environ, start_response) + else: + start_response("404 Not Found", [('Content-type', 'text/plain')]) + return ['Not Found'] diff --git a/examples/README.rst b/examples/flask_chat/README.rst similarity index 100% rename from examples/README.rst rename to examples/flask_chat/README.rst diff --git a/examples/app.py b/examples/flask_chat/app.py similarity index 100% rename from examples/app.py rename to examples/flask_chat/app.py diff --git a/examples/latency.py b/examples/flask_chat/latency.py similarity index 100% rename from examples/latency.py rename to examples/flask_chat/latency.py diff --git a/examples/requirements.txt b/examples/flask_chat/requirements.txt similarity index 100% rename from examples/requirements.txt rename to examples/flask_chat/requirements.txt diff --git a/examples/static/style.css b/examples/flask_chat/static/style.css similarity index 100% rename from examples/static/style.css rename to examples/flask_chat/static/style.css diff --git a/examples/templates/index.html b/examples/flask_chat/templates/index.html similarity index 100% rename from examples/templates/index.html rename to examples/flask_chat/templates/index.html diff --git a/examples/templates/latency.html b/examples/flask_chat/templates/latency.html similarity index 100% rename from examples/templates/latency.html rename to examples/flask_chat/templates/latency.html From bb3beb7af280a4de08cd01f552ef5e00be5bfd2e Mon Sep 17 00:00:00 2001 From: sillygod Date: Sun, 3 Jul 2016 14:15:40 +0800 Subject: [PATCH 2/2] add server generate event in example --- examples/django_chat/chat/sockets.py | 12 ++++++++++++ examples/django_chat/sdjango/__init__.py | 5 +++++ examples/django_chat/sdjango/sd_manager.py | 6 +----- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/examples/django_chat/chat/sockets.py b/examples/django_chat/chat/sockets.py index 664f98c..fc6d4b7 100644 --- a/examples/django_chat/chat/sockets.py +++ b/examples/django_chat/chat/sockets.py @@ -5,6 +5,13 @@ from sdjango import namespace online_user_num = 0 +def background_thread(): + + while True: + namespace.server.sleep(10) + namespace.server.emit("my response", {'data': 'Server generated event'}, namespace='/test') + + @namespace('/test') class TestNamespace: @@ -12,6 +19,11 @@ class TestNamespace: self.name = name self.request = None # django request object + def initialize(self): + """the server is already assigned when this function is called. + """ + namespace.server.start_background_task(background_thread) + def _get_socket(self, sid): socket = namespace.server.eio._get_socket(sid) return socket diff --git a/examples/django_chat/sdjango/__init__.py b/examples/django_chat/sdjango/__init__.py index 600aab4..c814eef 100644 --- a/examples/django_chat/sdjango/__init__.py +++ b/examples/django_chat/sdjango/__init__.py @@ -71,6 +71,8 @@ class namespace: methods = inspect.getmembers(instance, predicate=inspect.ismethod) + namespace.handler_container[self.name].append(instance) + for key, value in methods: if key.startswith('on_'): namespace.handler_container[self.name].append(value) @@ -85,6 +87,9 @@ class namespace: for name, handlers in namespace.handler_container.items(): + instance = handlers.pop(0) + instance.initialize() + for obj in handlers: event_name = obj.__name__.replace('on_', '').replace('_', ' ') server.on(event_name, obj, name) diff --git a/examples/django_chat/sdjango/sd_manager.py b/examples/django_chat/sdjango/sd_manager.py index 0e8bf86..e52fb71 100644 --- a/examples/django_chat/sdjango/sd_manager.py +++ b/examples/django_chat/sdjango/sd_manager.py @@ -3,20 +3,16 @@ from socketio.base_manager import BaseManager class SdManager(BaseManager): - """ + """Currently, there is no need to use custom manager """ def initialize(self, server): - # import pdb; pdb.set_trace() super().initialize(server) def connect(self, sid, namespace): """Register a client connection to a namespace. and set the django request object? """ - # TODO: process user authentication here? - # if 'django_request' in self.server.environ[sid]: - # print(self.server.environ[sid]['django_request'].user) self.enter_room(sid, namespace, None) self.enter_room(sid, namespace, sid)