├── templates
├── track.html
├── main.html
└── pymeetups.html
├── requirements.txt
├── .gitignore
├── request-track.py
├── README.md
├── LICENSE
└── app.py
/templates/track.html:
--------------------------------------------------------------------------------
1 |
2 |
Django District
3 |
4 | Django Distrct
5 | trackdata received.
6 |
7 |
8 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | bidict==0.21.2
2 | certifi==2020.12.5
3 | chardet==4.0.0
4 | click==7.1.2
5 | Flask==1.1.2
6 | Flask-SocketIO==5.0.1
7 | gevent==20.12.1
8 | gevent-websocket==0.10.1
9 | greenlet==0.4.17
10 | idna==2.10
11 | itsdangerous==1.1.0
12 | Jinja2==2.11.2
13 | MarkupSafe==1.1.1
14 | python-engineio==4.0.0
15 | python-socketio==5.0.4
16 | redis==3.5.3
17 | requests==2.25.1
18 | urllib3==1.26.2
19 | Werkzeug==1.0.1
20 | zope.event==4.5.0
21 | zope.interface==5.2.0
22 |
--------------------------------------------------------------------------------
/templates/main.html:
--------------------------------------------------------------------------------
1 |
2 | Django District
3 |
4 | Django Distrct
5 | {{ connected }}
6 | users are on this page right now.
7 |
8 |
10 |
11 |
12 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 |
5 | # C extensions
6 | *.so
7 |
8 | # Distribution / packaging
9 | .Python
10 | env/
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | lib/
17 | lib64/
18 | parts/
19 | sdist/
20 | var/
21 | *.egg-info/
22 | .installed.cfg
23 | *.egg
24 |
25 | # PyInstaller
26 | # Usually these files are written by a python script from a template
27 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
28 | *.manifest
29 | *.spec
30 |
31 | # Installer logs
32 | pip-log.txt
33 | pip-delete-this-directory.txt
34 |
35 | # Unit test / coverage reports
36 | htmlcov/
37 | .tox/
38 | .coverage
39 | .cache
40 | nosetests.xml
41 | coverage.xml
42 |
43 | # Translations
44 | *.mo
45 | *.pot
46 |
47 | # Django stuff:
48 | *.log
49 |
50 | # Sphinx documentation
51 | docs/_build/
52 |
53 | # PyBuilder
54 | target/
55 |
--------------------------------------------------------------------------------
/request-track.py:
--------------------------------------------------------------------------------
1 | import requests, json
2 |
3 | URL = 'http://localhost:5000/track'
4 |
5 | params = {
6 | 'dept': 'Dept',
7 | 'mcode': 'MCODE',
8 | 'device': 'Device',
9 | 'agency': 'Agency',
10 | 'name': 'Name',
11 | 'mobile': 'Mobile',
12 | 'parent_name': 'ParentName',
13 | 'parent_mobile': 'ParentMobile',
14 | 'call_date': '2020-12-30',
15 | 'image_url': 'https://example.com/image.jpg',
16 | 'lon': 127.269311,
17 | 'lat': 126.734086,
18 | 'geom': 'GeomText',
19 | 'init_time': '2020-12-30 16:59',
20 | 'address': 'Address',
21 | # 'addr': settlements
22 | }
23 | params = (
24 | ('name', params['name']),
25 | ('mobile', params['mobile']),
26 | ('parent_name', params['parent_name']),
27 | ('parent_mobile', params['parent_mobile']),
28 | ('address', params['address']),
29 | ('image_url', params['image_url'])
30 | )
31 | headers = {}
32 |
33 | res = requests.get(URL, headers=headers, params=params)
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Async Python Web Apps with WebSockets Demo Code
2 | Example code for my live coded demo at the January 2015
3 | [SF Python meetup](http://www.meetup.com/sfpython/events/219577721/)
4 | and updated for
5 | [Django District](http://www.meetup.com/django-district/events/220439364/)
6 | in March 2015.
7 |
8 | Note: I ran this demo with gunicorn behind an
9 | [Nginx](https://www.fullstackpython.com/nginx.html) reverse proxy with
10 | the appropriate WebSocket configuraiton .conf file. There can be issues
11 | upgrading the connection via the local Flask development server.
12 |
13 | Watch the [live-coded demo video for full effect](https://www.youtube.com/watch?v=L5YQbNrFfyw). The [slides are available](http://www.mattmakai.com/presentations/2015-sfpython-websockets.html)
14 | but fair warning, they won't make much sense without corresponding audio/video.
15 |
16 | This talk goes along with the
17 | [Full Stack Python WebSockets page](http://www.fullstackpython.com/websockets.html)
18 | and
19 | [Resources for WebSockets with Python](http://www.mattmakai.com/websockets-python-resources.html)
20 | blog post.
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Matthew Makai
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/templates/pymeetups.html:
--------------------------------------------------------------------------------
1 |
2 | Django District
3 |
4 | In what cities other than DC have you gone to Python meetups?
5 |
10 |
11 |
12 |
14 |
15 |
16 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | from gevent import monkey
2 | import cgi
3 | import redis
4 | from flask import Flask, render_template, request
5 | from flask_socketio import SocketIO
6 | from engineio.payload import Payload
7 |
8 | monkey.patch_all()
9 | Payload.max_decode_packets = 1024
10 |
11 | app = Flask(__name__)
12 | db = redis.StrictRedis('localhost', 6379, 0)
13 | socketio = SocketIO(app)
14 |
15 |
16 | @app.route('/')
17 | def main():
18 | return render_template('main.html')
19 |
20 |
21 | @app.route('/track')
22 | def track():
23 | print(request.args.get('name'), request.args.get('mobile'))
24 | data = {
25 | 'track': {
26 | 'name': request.args.get('name'),
27 | 'mobile': request.args.get('mobile'),
28 | 'parent_name': request.args.get('parent_name'),
29 | 'parent_mobile': request.args.get('parent_mobile'),
30 | 'image_url': request.args.get('image_url'),
31 | 'address': request.args.get('address')
32 | }}
33 | socketio.emit('msg', data, namespace='/dd')
34 | return render_template('track.html')
35 |
36 |
37 | @app.route('/pymeetups/')
38 | def pymeetups():
39 | return render_template('pymeetups.html')
40 |
41 |
42 | @socketio.on('connect', namespace='/dd')
43 | def ws_conn():
44 | c = db.incr('connected')
45 | socketio.emit('msg', {'count': c}, namespace='/dd')
46 | socketio.emit('msg', {'track': 'track-data'}, namespace='/dd')
47 |
48 |
49 | @socketio.on('disconnect', namespace='/dd')
50 | def ws_disconn():
51 | c = db.decr('connected')
52 | socketio.emit('msg', {'count': c}, namespace='/dd')
53 |
54 |
55 | @socketio.on('city', namespace='/dd')
56 | def ws_city(message):
57 | print(message['city'])
58 | socketio.emit('city', {'city': cgi.escape(message['city'])},
59 | namespace="/dd")
60 |
61 |
62 | if __name__ == '__main__':
63 | socketio.run(app, "0.0.0.0", port=5000)
64 |
--------------------------------------------------------------------------------