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

Артём Малышев (Positive Technologies) - Django ...

Артём Малышев (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.

Avatar for Moscow Python Meetup

Moscow Python Meetup PRO

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"