Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get query parameters from Django Channels?

I need to access the query parameter dict from Django Channels.

The url may look like this: ws://127.0.0.1:8000/?hello="world"

How do I retrieve 'world' like this: query_params["hello"]?

like image 937
Berry Avatar asked May 28 '17 03:05

Berry


2 Answers

On a websocket connect the message.content dictionary contains the query_string.

import urlparse
def ws_connect(message):
    params = urlparse.parse_qs(message.content['query_string'])
    hello = params.get('hello', (None,))[0]

The getting started documentation (http://channels.readthedocs.io/en/stable/getting-started.html) implies the query_string is included as part of the message.content path, but it doesn't appear to be the case.

Below is a working consumer.py for the chat application sample where the room is passed in the query string:

import urlparse
from channels import Group
from channels.sessions import channel_session

@channel_session
def ws_message(message):
    room = message.channel_session['room']
    Group("chat-{0}".format(room)).send({"text": "[{1}] {0}".format(message.content['text'], room)})

@channel_session
def ws_connect(message):
    message.reply_channel.send({"accept": True})
    params = urlparse.parse_qs(message.content['query_string'])
    room = params.get('room',('Not Supplied',))[0]
    message.channel_session['room'] = room
    Group("chat-{0}".format(room)).add(message.reply_channel)

@channel_session
def ws_disconnect(message):
    room = message.channel_session['room']
    Group("chat-{0}".format(room)).discard(message.reply_channel)
like image 89
clockwatcher Avatar answered Nov 04 '22 09:11

clockwatcher


Updated for Channel 3:

from urllib.parse import parse_qs

# Types
class Scope(TypedDict):   
    query_string: bytes

scope: Scope
query_params: Dict[str, List[str]]

# Parse query_string
query_params = parse_qs(scope["query_string"].decode())

print(query_params["access_token"][-1])

If you were doing this a lot, you could put it in a middleware and wrap your ASGI application in it. Something like:

class QueryParamsMiddleware(BaseMiddleware):
    async def __call__(self, scope, receive, send):
        scope = dict(scope)

        scope["query_params"] = parse_qs(scope["query_string"].decode())

        return await super().__call__(scope, receive, send)
like image 34
Danielle Madeley Avatar answered Nov 04 '22 09:11

Danielle Madeley