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

Артём Малышев (Positive Technologies) - Django Channels - ответ современному вебу

Артём Малышев (Positive Technologies) - Django Channels - ответ современному вебу

Доклад с Moscow Python Conf 2016 (http://conf.python.ru)
Видео: https://conf.python.ru/django-channels-otvet-sovremennomu-vebu/

Я senior python developer в компании Positive Technologies. Последние два года занимаюсь разработкой распределённых систем. Спикер PyCon Russia, MoscowPython и Rannts Meetup. В докладе я расскажу о назначение и устройстве Django Channels. Давно прошли времена, когда все сайты работали в режиме "запрос-ответ". Пользователи хотят интерактивности и отзывчивости, программисты хотят websocket'ы, HTTP/2 стремительно набирает популярность. Классические WSGI фреймворки перестают соответствовать реалиям жизни. Вы узнаете каким образом в Django реализована поддержка асинхронных протоколов, решение каких задач можно отдать этой технологии, а где лучше использовать tornado или aiohttp.

Moscow Python Meetup

October 12, 2016
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. 5 WSGI def app(environ, callback): status, headers = '200 OK',

    [] callback(status, headers) return ['Hello world!\n']
  2. 6

  3. 9

  4. 11

  5. 12

  6. 13

  7. 14

  8. 18 CHANNEL IS an ordered, first-in first-out queue with message

    expiry and at-most-once delivery to only one listener at a time
  9. 21 ROUTING from channels.routing import route from myapp.consumers import ws_message

    channel_routing = [ route('websocket.receive', ws_message), ]
  10. 23 ASGI APP import os from channels.asgi import get_channel_layer os.environ.setdefault(

    'DJANGO_SETTINGS_MODULE', 'myproject.settings', ) channel_layer = get_channel_layer()
  11. 26

  12. 28 CONSUMERS from channels import Group def ws_connect(message): Group('chat').add(message.reply_channel) def

    ws_disconnect(message): Group('chat').discard(message.reply_channel) def ws_message(message): Group('chat').send({ 'text': message.content['text'], })
  13. 29 ROUTING from channels.routing import route from myapp.consumers import *

    channel_routing = [ route('websocket.connect', ws_connect), route('websocket.disconnect', ws_disconnect), route('websocket.receive', ws_message), ]
  14. 31 BASE CONSUMER from channels.generic import BaseConsumer class MyConsumer(BaseConsumer): method_mapping

    = { 'channel.name.here': 'method_name', } def method_name(self, message, **kwargs): pass
  15. 32 WEBSOCKET CONSUMER from channels.generic import WebsocketConsumer class MyConsumer(WebsocketConsumer): def

    connection_groups(self): return ['chat'] def connect(self, message): pass def receive(self, text=None, bytes=None): self.send(text=text, bytes=bytes)
  16. 33 ROUTING from channels import route_class from myapp import consumers

    channel_routing = [ route_class(consumers.MyConsumer), ]
  17. 35 FILTERS // app.js s = new WebSocket('ws://localhost:8000/chat/') # routing.py

    route('websocket.connect', ws_connect, path=r'^/chat/$')
  18. 36 INCLUDES from channels import route, include blog_routes = [

    route('websocket.connect', blog, path=r'^/stream/'), ] routing = [ include(blog_routes, path=r'^/blog'), ]
  19. 39 ROUTING from channels import route_class, route from .consumers import

    Demultiplexer, ws_message channel_routing = [ route_class(Demultiplexer, path='^/binding/'), route('binding.intval', ws_message), ]
  20. 42 CHANNEL SESSION from channels.sessions import channel_session @channel_session def ws_connect(message):

    room = message.content['path'] message.channel_session['room'] = room Group('chat-%s' % room).add( message.reply_channel )
  21. 45 ENFORCE ORDERING from channels.generic import WebsocketConsumer class MyConsumer(WebsocketConsumer): http_user

    = True slight_ordering = True strict_ordering = False def connection_groups(self, **kwargs): return ['chat']
  22. 47 BIND MODEL class IntegerValueBinding(WebsocketBinding): model = IntegerValue stream =

    'intval' fields = ['name', 'value'] def group_names(self, instance, action): return ['intval-updates'] def has_permission(self, user, action, pk): return True
  23. 50 CHANNEL IMPLEMENTATION >> SET "b6dc0dfce" "\x81\xa4text\xachello" >> RPUSH "websocket.send!sGOpfny"

    "b6dc0dfce" >> EXPIRE "b6dc0dfce" "60" >> EXPIRE "websocket.send!sGOpfny" "61"
  24. 51 GROUP IMPLEMENTATION >> type group:chat zset >> ZRANGE group:chat

    0 1 WITHSCORES 1) "websocket.send!sGOpfny" 2) "1476199781.8159261"