Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[PyConAR 2017] Django Channeled

[PyConAR 2017] Django Channeled

Instead of just receiving and answering requests – one by one – Channels changes the way Django works, towards an event-driven approach. With that, we now have access to WebSockets and others asynchronous wonders. Event driven for the win!

In this talk, we are going to see the asynchronous concepts and who to iplement them with Django Channels.

The D is silent.

67e79c99f3b6e205ebc68a6ab91545ad?s=128

Jonatas Baldin

November 18, 2017
Tweet

Transcript

  1. DJANGO C H A N N E L E D

    “jojo” @jonatasbaldin
  2. DJANGO IS AN OLD FRAMEWORK SOLVING OLD PROBLEMS

  3. client makes a request server process it and sends a

    response client displays the response
  4. client makes a request Django receives an HTTP Request routes

    it to a View which returns an HTTP Response client displays the response
  5. In 2017, web apps need to know how to display

    a feed in your timeline, from thousands of people around the world, as soon as they publish new content, in less than one second
  6. Real-Time Web Applications

  7. SSE WebRTC Streaming

  8. WebSockets

  9. WebSocket is a bidirectional and message-oriented transport layer, allowing clients

    and servers to exchange data using a persistent connection
  10. WebSocket is a bidirectional and message-oriented transport layer, allowing clients

    and servers to exchange data using a persistent connection
  11. WebSocket is a bidirectional and message-oriented transport layer, allowing clients

    and servers to exchange data using a persistent connection
  12. WebSocket is a bidirectional and message-oriented transport layer, allowing clients

    and servers to exchange data using a persistent connection
  13. It has a simple JavaScript API .onopen() .onmessage() .send() .onerror()

    .onclose()
  14. WebSocket is not HTTP!

  15. server establishes the connection and the data flows client connects

    to the WebSocket server
  16. client connects to the WebSocket server Django doesn’t understand it

    and makes the client sad :(
  17. DJANGO IS AN OLD FRAMEWORK SOLVING OLD PROBLEMS

  18. DJANGO IS AN OLD FRAMEWORK SOLVING OLD PROBLEMS BUT IT

    CAN BE EXTENDED TO SOLVE NEW ONES
  19. Channels

  20. Enables Django to handle WebSockets and other asynchronous tasks using

    familiar Django design patterns
  21. Before Channels

  22. view WSGI client HTTP Request HTTP Response

  23. After Channels

  24. Worker Channels Backend client message message ASGI

  25. Let’s break it piece by piece

  26. As WSGI doesn’t understand WebSockets, a new spec was created

    – ASGI – which basically replaces WSGI
  27. Channels ships with an ASGI implementation server, called Daphne

  28. # asgi.py import os from channels.asgi import get_channel_layer os.environ.setdefault( 'DJANGO_SETTINGS_MODULE',

    ‘wsquiz.settings' ) channel_layer = get_channel_layer()
  29. Daphne is executed like any other WSGI server, just run

    the command $ daphne project.asgi:channel_layer
  30. Note that Daphne also speaks HTTP, so you can completely

    remove your WSGI server
  31. Worker Channels Backend client message message ASGI (the new WSGI

    - Daphne)
  32. A Channel is basically a named task queue used to

    store and process messages
  33. It’s a FIFO queue with message expiry and at-most-once delivery

  34. It’s a FIFO queue with message expiry and at-most-once delivery

  35. It’s a FIFO queue with message expiry and at-most-once delivery

  36. It’s a FIFO queue with message expiry and at-most-once delivery

  37. Each message has a unique reply_channel that is used to

    send a response to the client
  38. # consumers.py def ws_connect(message): message.reply_channel.send({'accept': True}) def ws_message(message): message.reply_channel.send(message[‘text’]) #

    routing.py channel_routing = [ route('websocket.connect', ws_connect), route('websocket.receive', ws_message), ]
  39. We can also assign the reply_channel to a Channel Group,

    allowing the broadcast of messages
  40. # consumers.py def ws_connect(message): Group('tweets').add(message.reply_channel) # models.py class Tweet(models.Model): text

    = models.CharField(max_length=140) def save(self, *args, **kwargs): result = super().save(*args, **kwargs) Group('tweets').send({'text': self.text}) return result # routing.py channel_routing = [ route('websocket.connect', ws_connect), ]
  41. These messages can be stored in different ways

  42. In-Memory testing and single-process POSIX IPC single-machine REDIS/RabbitMQ network layer

  43. # settings.py CHANNEL_LAYERS = { 'default': { 'BACKEND': 'asgi_redis.RedisChannelLayer', 'CONFIG':

    { 'hosts': [(REDIS_HOST, 6379)], }, 'ROUTING': 'wsquiz.routing.channel_routing', } }
  44. Worker Channels Backend (routing and datastore) client message message ASGI

    (the new WSGI – Daphne)
  45. The worker is responsible to listen to Channels and consume

    messages once they are ready
  46. # consumers.py def ws_message(message): message.reply_channel.send(message['text']) # routing.py channel_routing = [

    route('websocket.receive', ws_message), ]
  47. Channels comes with a Django management command for running workers!

    $ python manage.py runworker
  48. Worker (Django management command) Channels Backend (routing and datastore) client

    message message ASGI (the new WSGI)
  49. To develop the client – like a JavaScript application –

    Channels comes with a library called WebSocketBridge
  50. const webSocketBridge = new channels.WebSocketBridge(); webSocketBridge.connect('/ws/'); webSocketBridge.listen(function(data) { console.log(data); });

  51. Worker (Django management command) Channels Backend (routing and datastore) client

    (WebSocketBridge) message message ASGI (the new WSGI)
  52. Summing up…

  53. Worker Channels Backend client message message ASGI

  54. Worker Channels Backend client message message ASGI (the new WSGI

    - Daphne)
  55. Worker Channels Backend (routing and datastore) client message message ASGI

    (the new WSGI - Daphne)
  56. Worker (Django management command) Channels Backend (routing and datastore) client

    message message ASGI (the new WSGI - Daphne)
  57. Worker (Django management command) Channels Backend (routing and datastore) client

    (WebSocketBridge) message message ASGI (the new WSGI - Daphne)
  58. “But I still need to run normal Django”

  59. Worker Channels Backend client message message ASGI WSGI view reverse

    proxy request response
  60. Testing is simple! $ python manage.py runserver

  61. Testing is simple! $ python manage.py runserver **not recommended for

    production**
  62. Channels changes the way Django runs to be event-oriented

  63. The WSQuiz

  64. https://wsquiz.herokuapp.com/

  65. Things to take into consideration

  66. WebSocket has TLS, please use it!

  67. WebSocket and Subprotocols

  68. Tests, documentation and monitoring

  69. Today, all of the major browsers support WebSockets, but write

    fallbacks for critical core business
  70. Channels is a young project, but the first Django official

    app
  71. Let’s study! channels.readthedocs.io github.com/andrewgodwin/channels-examples github.com/jonatasbaldin/wsquiz

  72. DJANGO C H A N N E L E D

    @jonatasbaldin
  73. DJANGO C H A N N E L E D

    @jonatasbaldin the D is silent