PyConES 2016

Channels is coming: real-time web in Django

José Manuel Rivas / @jmrivas86

¡Hola Mundo!

Me llamo José Manuel Rivas y soy

Python/Django developer en

Django, HTTP y WSGI

Django se ha basado en un modelo de peticiones y respuestas

¿Qué es Channels?

Es anunciado como proyecto oficial de Django el 9 de Septiembre de 2016

La Fundación Mozilla apoyó en diciembre de 2015 a este proyecto con $150,000

¿Qué es Channels?

Channels añade una capa nueva que permite principalmente 2 características importantes:

  • Websockets
  • Tareas en segundo plano
  • ...
  • HTTP2 Server push
  • Soporte de Sesión y autenticación para WebSockets
  • Login de usuarios en WebSockets basados en las cookies
  • Posibilidad de ampliación a otros protocolos o tipos de eventos WebRTC, SMS...)

¿Hay otras implementaciones de websockets para Django?

Sí y no.

  • Sí, hay soluciones para implementar websockets en Django.
  • No, no hay nada "estandar".

Ejemplos de implementaciones para websocket en python

  • AutobahnPython - WebSocket & WAMP for Python on Twisted and asyncio.
  • Crossbar - Open-source Unified Application Router (Websocket & WAMP for Python on Autobahn).
  • django-socketio - WebSockets for Django.
  • WebSocket-for-Python - WebSocket client and server library for Python 2 and 3 as well as PyPy.

Vale, ¿y cómo funciona esto?

Video de la PyCon 2016 en Portland de parte Andrew Godwin.

  • Channel backend: Responsable del transporte de mensajes.
  • Worker server: Escuchan en todos los canales pertinentes y ejecutan código del consumer cuando un mensaje está listo.
  • Interface server: Se comunica entre Django y el mundo exterior. Esto incluye un adaptador de WSGI, así como un servidor independiente WebSocket.

Conceptos:

  • Channel: Cola FIFO con envío y recepción de muchas operaciones. Su nombre es una cadena. Como máximo una vez (at-most-once) la entrega a un solo listener a la vez.
  • Group: Nombre conjunto de canales con operaciones de Añadir/quitar/envío
  • Messages: Representación de las sesiones http y websockets

Ejemplos

LIVEBLOG

Queremos que la gente tenga las nuevas entradas del blog publicadas sin refrescar la página.

LIVEBLOG

  • La gente abre un WebSocket cuando acceden en la página
  • El WebSocket se agrega a un grupo
  • Cuando se guarda el post, enviamos el mensaje a ese grupo

El WebSocket se agrega a un grupo

                    
# in consumers.py
def ws_connect(message):
    Group("liveblog").add(message.reply_channel)
                    
                

Cuando se guarda el post (save del model), enviamos el mensaje a ese grupo

                    
                        class BlogPost(models.Model):
     ...
     def save(self, *args, **kwargs):
     ...
     Group("liveblog").send({
     "text": json.dumps({"id": self.id}),
     })
                    
                

CHAT

La gente puede enviar mensajes al chat y le llegará a todo el mundo conectado

CHAT

  • Cuando las personas entran en un chat, se unen a un grupo.
  • Cuando recibimos un mensaje lo enviamos al grupo.

Cuando las personas entran en un chat, se unen a un grupo.

                    
# in consumers.py
def ws_connect(message):
    Group("chat").add(message.reply_channel)
                    
                

Cuando recibimos un mensaje lo enviamos al grupo

                    
                        def ws_receive(message):
 Group("chat").send({
 "text": message["text"],
 })
                    
                

Y hacemos saber a Django los consumers que manejan los distintos eventos

                    
                        # in routing.py
        routing = [
         route("websocket.connect", consumers.ws_connect),
         route("websocket.receive", consumers.ws_receive),
        ]
                    
                

DEMO

La Demo consiste en una plataforma minimalista para compartir ficheros en tiempo real. Hay que tener en cuenta que la idea de esta prueba de concepto es mostrar el poder de transformar una aplicación tradicional de Django en tiempo real con sólo unas pocas líneas de código.

El código de la Demo "PatiPamiFile" está disponible en mi github