mirror of
https://github.com/django/daphne.git
synced 2025-07-12 17:02:18 +03:00
Update concepts doc to not use decorators
This commit is contained in:
parent
c6527bebf1
commit
d4c7f2db20
|
@ -60,21 +60,25 @@ How do we use channels?
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
That's what a channel is, but how is Django using them? Well, inside Django
|
That's what a channel is, but how is Django using them? Well, inside Django
|
||||||
you can connect a function to consume a channel, like so::
|
you can write a function to consume a channel, like so::
|
||||||
|
|
||||||
from channels.decorators import consumer
|
def my_consumer(message):
|
||||||
|
|
||||||
@consumer("channel-name")
|
|
||||||
def my_consumer(something, **kwargs):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
And then assign a channel to it like this in the channel backend settings::
|
||||||
|
|
||||||
|
"ROUTING": {
|
||||||
|
"some-channel": "myapp.consumers.my_consumer",
|
||||||
|
}
|
||||||
|
|
||||||
This means that for every message on the channel, Django will call that
|
This means that for every message on the channel, Django will call that
|
||||||
consumer function with the message as keyword arguments (messages are always
|
consumer function with a message object (message objects have a "content"
|
||||||
a dict, and are mapped to keyword arguments for send/receive).
|
attribute which is always a dict of data, and a "channel" attribute which
|
||||||
|
is the channel it came from, as well as some others).
|
||||||
|
|
||||||
Django can do this as rather than run in a request-response mode, Channels
|
Django can do this as rather than run in a request-response mode, Channels
|
||||||
changes Django so that it runs in a worker mode - it listens on all channels
|
changes Django so that it runs in a worker mode - it listens on all channels
|
||||||
that have consumers declared, and when a message arrives on one, runs the
|
that have consumers assigned, and when a message arrives on one, runs the
|
||||||
relevant consumer.
|
relevant consumer.
|
||||||
|
|
||||||
In fact, this is illustrative of the new way Django runs to enable Channels to
|
In fact, this is illustrative of the new way Django runs to enable Channels to
|
||||||
|
@ -98,15 +102,15 @@ slightly more complex abstraction than that presented by Django views.
|
||||||
A view takes a request and returns a response; a consumer takes a channel
|
A view takes a request and returns a response; a consumer takes a channel
|
||||||
message and can write out zero to many other channel messages.
|
message and can write out zero to many other channel messages.
|
||||||
|
|
||||||
Now, let's make a channel for requests (called ``django.wsgi.request``),
|
Now, let's make a channel for requests (called ``django.wsgi.request``),
|
||||||
and a channel per client for responses (e.g. ``django.wsgi.response.o4F2h2Fd``),
|
and a channel per client for responses (e.g. ``django.wsgi.response.o4F2h2Fd``),
|
||||||
with the response channel a property (``reply_channel``) of the request message.
|
with the response channel a property (``reply_channel``) of the request message.
|
||||||
Suddenly, a view is merely another example of a consumer::
|
Suddenly, a view is merely another example of a consumer::
|
||||||
|
|
||||||
@consumer("django.wsgi.request")
|
# Listens on django.wsgi.request.
|
||||||
def my_consumer(reply_channel, **request_data):
|
def my_consumer(message):
|
||||||
# Decode the request from JSON-compat to a full object
|
# Decode the request from JSON-compat to a full object
|
||||||
django_request = Request.decode(request_data)
|
django_request = Request.decode(message.content)
|
||||||
# Run view
|
# Run view
|
||||||
django_response = view(django_request)
|
django_response = view(django_request)
|
||||||
# Encode the response into JSON-compat format
|
# Encode the response into JSON-compat format
|
||||||
|
@ -171,7 +175,6 @@ Say I had a live blog where I wanted to push out updates whenever a new post is
|
||||||
saved, I would register a handler for the ``post_save`` signal and keep a
|
saved, I would register a handler for the ``post_save`` signal and keep a
|
||||||
set of channels (here, using Redis) to send updates to::
|
set of channels (here, using Redis) to send updates to::
|
||||||
|
|
||||||
|
|
||||||
redis_conn = redis.Redis("localhost", 6379)
|
redis_conn = redis.Redis("localhost", 6379)
|
||||||
|
|
||||||
@receiver(post_save, sender=BlogUpdate)
|
@receiver(post_save, sender=BlogUpdate)
|
||||||
|
@ -183,10 +186,10 @@ set of channels (here, using Redis) to send updates to::
|
||||||
content=instance.content,
|
content=instance.content,
|
||||||
)
|
)
|
||||||
|
|
||||||
@consumer("django.websocket.connect")
|
# Connected to django.websocket.connect
|
||||||
def ws_connect(path, reply_channel, **kwargs):
|
def ws_connect(message):
|
||||||
# Add to reader set
|
# Add to reader set
|
||||||
redis_conn.sadd("readers", reply_channel)
|
redis_conn.sadd("readers", message.reply_channel.name)
|
||||||
|
|
||||||
While this will work, there's a small problem - we never remove people from
|
While this will work, there's a small problem - we never remove people from
|
||||||
the ``readers`` set when they disconnect. We could add a consumer that
|
the ``readers`` set when they disconnect. We could add a consumer that
|
||||||
|
@ -219,14 +222,13 @@ we don't need to; Channels has it built in, as a feature called Groups::
|
||||||
content=instance.content,
|
content=instance.content,
|
||||||
)
|
)
|
||||||
|
|
||||||
@consumer("django.websocket.connect")
|
# Connected to django.websocket.connect and django.websocket.keepalive
|
||||||
@consumer("django.websocket.keepalive")
|
def ws_connect(message):
|
||||||
def ws_connect(path, reply_channel, **kwargs):
|
|
||||||
# Add to reader group
|
# Add to reader group
|
||||||
Group("liveblog").add(reply_channel)
|
Group("liveblog").add(message.reply_channel)
|
||||||
|
|
||||||
Not only do groups have their own ``send()`` method (which backends can provide
|
Not only do groups have their own ``send()`` method (which backends can provide
|
||||||
an efficient implementation of), they also automatically manage expiry of
|
an efficient implementation of), they also automatically manage expiry of
|
||||||
the group members. You'll have to re-call ``Group.add()`` every so often to
|
the group members. You'll have to re-call ``Group.add()`` every so often to
|
||||||
keep existing members from expiring, but that's easy, and can be done in the
|
keep existing members from expiring, but that's easy, and can be done in the
|
||||||
same handler for both ``connect`` and ``keepalive``, as you can see above.
|
same handler for both ``connect`` and ``keepalive``, as you can see above.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user