Asynchronous WebSockets using Django

Similar documents
MIT AITI Python Software Development Lab DJ1:

Webdev: Building Django Apps. Ryan Fox Andrew Glassman MKE Python

Lecture 10(-ish) Web [Application] Frameworks

Graphene Documentation

django-plotly-dash Documentation Mark Gibbs

Introduction. Using HTML 5 WebSockets we can dramatically reduce unnecessary network traffic and latency Haim Michael. All Rights Reserved.

django-private-chat Documentation

Django-frontend-notification Documentation

Tangent MicroServices Documentation

ganetimgr Documentation

Django MFA Documentation

django-xross Documentation

Django urls Django Girls Tutorial

django-osm-field Release 0.3.1

Django CBTools Documentation

open-helpdesk Documentation

django-embed-video Documentation

silk Documentation Release 0.3 Michael Ford

TailorDev Contact Documentation

Django Groups Manager Documentation

wagtail-robots Documentation

generates scaffolding/framework for models, views

DJOAuth2 Documentation

Django Image Tools Documentation

Rapid Development with Django and App Engine. Guido van Rossum May 28, 2008

Tomasz Szumlak WFiIS AGH 23/10/2017, Kraków

Trunk Player Documentation

Django IPRestrict Documentation

Django File Picker Documentation

MapEntity Documentation

django-embed-video Documentation

Building a Django Twilio Programmable Chat Application

Bambu API Documentation

widgets, events, layout loosely similar to Swing test browser, or plugin for testing with real browser on local system

Tango with Django. Chapter 1: Overview. 1. Overview. 2. The N tier architecture of web applications

django-audiofield Documentation

CE419 Web Programming. Session 15: Django Web Framework

Django PAM Documentation

django-templation Documentation

django-inplaceedit Documentation

django-avatar Documentation

django-avatar Documentation

Quoting Wikipedia, software

django-reinhardt Documentation

webkitpony Documentation

IERG 4080 Building Scalable Internet-based Services

Reminders. Full Django products are due next Thursday! CS370, Günay (Emory) Spring / 6

kaleo Documentation Release 1.5 Eldarion

Django Localized Recurrence Documentation

django-rest-auth Documentation

CID Documentation. Release Francis Reyes

django-embed-video Documentation

Django File Picker Documentation

django cms Documentation

django-notifier Documentation

micawber Documentation

정재성

django-audit-log Documentation

Django Groups Manager Documentation

django-organizations Documentation

django-messages Documentation

Gargoyle Documentation

Django Admin Sortable Documentation

Ninja Typers Web Application Design Document By Marvin Farrell C

django simple pagination Documentation

The Django Web Framework Part VI

Django Deployment & Tips daybreaker

django-getpaid Documentation

django-cas Documentation

Python Schema Generator Documentation

Unit 6 IoT Physical Servers, Cloud Offerings & IoT Case Studies. By Mahesh R. Sanghavi

django-oauth2-provider Documentation

Django_template3d Documentation

Linguistic Architecture

django-geoip Documentation

django-auditlog Documentation

django-stored-messages Documentation

django-ad-code Documentation

django-autocomplete-light Documentation

ska Documentation Release Artur Barseghyan

Django EL(Endless) Pagination Documentation

Django starting guide

django-app-metrics Documentation

django-teamwork Documentation

Django by errors. Release 0.2. Sigurd Gartmann

Diving into Big Data Workshop

django-telegram-bot Documentation

Bricks Documentation. Release 1.0. Germano Guerrini

Django Synctool Documentation

Building APIs with Django and Django Rest Framework

cmsplugin-blog Release post 0 Øyvind Saltvik

django-cron Documentation

django-photologue Documentation

django-intercom Documentation

datapusher Documentation

Django Standalone Apps

Django design patterns Documentation

Django-danceschool Documentation

django-celery Documentation

Python. Django. (Web Application Framework - WAF) PyCharm. (Integration Development Environment - IDE)

Transcription:

Asynchronous WebSockets using Django 2017-05-18

OUTLINE OF THE TALK WEBSOCKETS What is Websocket? Why are they important? DJANGO CHANNELS Introduction Changes to WSGI server EXAMPLE Django code Django channels code

WEBSOCKETS (A.K.A. ASYNCHRONOUS WEBSOCKETS) WebSocket is a new computer communication protocol It enables a continuous bi-directional communication channel between client and server Transmissions are made over a single long-held TCP connection Messages are instantly distributed with little overhead resulting in a very low latency connection Communication can be asynchronous

WEBSOCKETS VS HTTP

WHY WEBSOCKETS ARE IMPORTANT? Major evolution of client/server web technology Enables true page responsiveness VS

DJANGO CHANNELS INTRODUCTION Channels is an offical Django project which extends Django It enables WebSocket handling in similar way to views Background tasks can be run in the same server as Django

DJANGO WSGI SERVER

DJANGO ASGI SERVER

models.py This example is taken from Jacob Kaplan-Moss blog. And his git repository. class Room(models.Model): name = models.textfield() label = models.slugfield(unique=true) class Message(models.Model): room = models.foreignkey(room, related_name='messages') handle = models.textfield() message = models.textfield() timestamp = models.datetimefield(default=timezone.now, db_index=true) All previous Django functionality works as before

urls.py urlpatterns = [ url(r'ˆ$', views.about, name='about'), url(r'ˆnew/$', views.new_room, name='new_room'), url(r'ˆ(?p<label>[\w-]{,50})/$', views.chat_room, name='chat_room' ]

views.py def chat_room(request, label): # If the room with the given label doesn't exist, # automatically create it upon first visit (a la etherpad). room, created = Room.objects.get_or_create(label=label) # We want to show the last 50 messages, ordered most-recent-last messages = reversed(room.messages.order_by('-timestamp')[:50]) return render(request, "chat/room.html", { 'room': room, 'messages': messages, }) def new_room(request): new_room = None while not new_room: with transaction.atomic(): label = haikunator.haikunate() if Room.objects.filter(label=label).exists(): continue new_room = Room.objects.create(label=label) return redirect(chat_room, label=label)

chat/room.html <h1>{{ room.label }}</h1> <ol id="chat"> {% for message in messages %} <li>{{ message.formatted_timestamp }} {{ message.handle }} {{ message.message }}</li> {% endfor %} </ol> <form id="chatform"> <p>say something: <input id="handle" type="text" placeholder="your name:"> <input id="message" type="text" placeholder="message"> <button type="submit" id="go">say it</button></p> </form> <script type="text/javascript" src="jquery-1.12.1.min.js"></script> <script type="text/javascript" src="chat.js"></script>

chat.js $(function() { var ws_scheme = window.location.protocol == "https:"? "wss" : "ws var chatsock = new WebSocket(ws_scheme + '://' + window.location.host + "/chat" + window.location.pathname); }); chatsock.onmessage = function(message) { var data = JSON.parse(message.data); var chat = $("#chat") var ele = $('<li>' + data.timestamp + ' ' + data.handle + ' ' chat.append(ele) }; $("#chatform").on("submit", function(event) { var message = { handle: $('#handle').val(), message: $('#message').val(), } chatsock.send(json.stringify(message)); $("#message").val('').focus(); return false; });

settings.py $ pip install channels $ pip install asgi_redis in settings.py: INSTALLED_APPS += [channels] CHANNEL_LAYERS = { "default": { "BACKEND": "asgi_redis.redischannellayer", "CONFIG": { "hosts": ['redis://localhost:6379'], }, "ROUTING": "chat.routing.channel_routing", }, }

routing.py from channels.routing import route from. import consumers channel_routing = [ # Wire up websocket channels to our consumers: route('websocket.connect', consumers.ws_connect), route('websocket.receive', consumers.ws_receive, path='ˆ*'), route('websocket.disconnect', consumers.ws_disconnect), ]

consumers.py from channels import Group from channels.sessions import channel_session from.models import Room @channel_session def ws_connect(message): prefix, label = message['path'].strip('/').split('/') room = Room.objects.get(label=label) Group('chat-' + label).add(message.reply_channel) message.channel_session['room'] = room.label @channel_session def ws_receive(message): label = message.channel_session['room'] room = Room.objects.get(label=label) data = json.loads(message['text']) m = room.messages.create(handle=data['handle'], message=data['mess Group('chat-'+label).send({'text': json.dumps(m.as_dict())}) @channel_session def ws_disconnect(message): label = message.channel_session['room'] Group('chat-'+label).discard(message.reply_channel)

asgi.py import os import channels.asgi os.environ.setdefault("django_settings_module", "chat.settings") channel_layer = channels.asgi.get_channel_layer() In the future, Django will probably auto-generate this file, like it currently does for wsgi.py

RUNNING THE CODE Install redis-server and run it: $ sudo apt-get update $ sudo apt-get install redis-server $ redis-server Run the project: $ python manage.py migrate $ python manage.py runserver

DATA BINDING (INBOUNDING) Data binding framework automates the process of tying Django models into frontend view (from channels docs) from django.db import models from channels.binding.websockets import WebsocketBinding class IntegerValue(models.Model): name = models.charfield(max_length=100, unique=true) value = models.integerfield(default=0) class IntegerValueBinding(WebsocketBinding): model = IntegerValue stream = "intval" fields = ["name", "value"] @classmethod def group_names(cls, instance): return ["intval-updates"] def has_permission(self, user, action, pk): return True

DATA BINDING (OUTBOUNDING) from channels.generic.websockets import WebsocketDemultiplexer from.binding import IntegerValueBinding class Demultiplexer(WebsocketDemultiplexer): consumers = { "intval": IntegerValueBinding.consumer, } def connection_groups(self): return ["intval-updates"]

Thank you!