DEV Community

Cover image for How to Add Websockets to a Django App without Extra Dependencies

How to Add Websockets to a Django App without Extra Dependencies

Jayden Windle on February 06, 2020

Note: This post was originally published on my blog. Now that Django 3.0 ships with ASGI support out of the box, adding Websockets to your Django ...
Collapse
 
mehdimortaz profile image
Parsezan

Thank you for this post. I have a question, how possible send a message to WebSocket from Django views? by above I just can do something just when a client sends me a message.

Collapse
 
lautaronavarro profile image
Lautaro Navarro

I have an implementation for this, maybe you would like to take a look at it!

Basically, the queue can be change by any other type of queue which allows you to exchange data between routines and threads (Each requests to django_application are new threads, you can check that, requests to websocket_application share the same thread)

Collapse
 
htrampe profile image
Holger Trampe • Edited

Did someone found a good solution? The above information is great, but i can do something like that with ajax and json-response. A way from view to the client-websockets is much more interesting. THX!

Collapse
 
lautaronavarro profile image
Lautaro Navarro

That's an excellent question, and I'd like to know the answer, let me know if you find out a way

Collapse
 
piexpie profile image
Piyush • Edited

Hi, I am encountering errrors when creating a websocket connection,

ws = new WebSocket('ws://localhost:8000/')
WebSocket {url: "ws://localhost:8000/", readyState: 0, bufferedAmount: 0, onopen: null, onerror: null, …}
VM50:1 WebSocket connection to 'ws://localhost:8000/' failed: Error during WebSocket handshake: Unexpected response code: 400
Enter fullscreen mode Exit fullscreen mode

And the uvicorn request says: "WARNING: Unsupported upgrade request."

How do I fix this issue?

Thanks.

And also this

ws = new WebSocket('wss://localhost:8000/')
WebSocket {url: "wss://localhost:8000/", readyState: 0, bufferedAmount: 0, onopen: null, onerror: null, …}
ws = new WebSocket('ws://localhost:8000/')
WebSocket {url: "ws://localhost:8000/", readyState: 0, bufferedAmount: 0, onopen: null, onerror: null, …}
ws.onmessage = event => console.log(event.data)
event => console.log(event.data)
ws.send("ping")
VM92:1 Uncaught DOMException: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.
    at <anonymous>:1:4
(anonymous) @ VM92:1
ws.send("ping")
VM97:1 Uncaught DOMException: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.
    at <anonymous>:1:4
(anonymous) @ VM97:1
VM75:1 WebSocket connection to 'wss://localhost:8000/' failed: WebSocket opening handshake timed out
(anonymous) @ VM75:1
VM82:1 WebSocket connection to 'ws://localhost:8000/' failed: Error during WebSocket handshake: Unexpected response code: 400
Enter fullscreen mode Exit fullscreen mode
Collapse
 
arjhe profile image
ARJhe • Edited

pip install uvicorn
did not deal with WebSocket configuration.

# h11_impl.py L:91
self.ws_protocol_class = config.ws_protocol_class
Enter fullscreen mode Exit fullscreen mode

config.ws_protocol_class is None
so in L:264 you will get a warning.

# h11_impl.py L:264
        if upgrade_value != b"websocket" or self.ws_protocol_class is None:
            msg = "Unsupported upgrade request."
            self.logger.warning(msg)
Enter fullscreen mode Exit fullscreen mode

try: pip install uvicorn[standard]
See ref

Collapse
 
jesuszerpa profile image
Jesús Abraham Zerpa Maldonado • Edited

Thanks for your post, i have a question, how i can use with nginx, i am trying deploy my project and i have the next case, the event['type'] is http.request i need websocket.connect, i belive is by my nginx configuration but i am not sure, my configuration is

location /ws/ {
                try_files $uri @proxy_to_app;
        }
location / {
           #include proxy_params;
           #proxy_pass https://unix:/run/gunicorn.sock;
           proxy_pass http://0.0.0.0:8000;

           #websocket support
           proxy_http_version 1.1;
           proxy_set_header Upgrade $http_upgrade;
           #proxy_set_header Connection "upgrade";
           proxy_set_header Host $host;
           #proxy_redirect off;
#proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           #proxy_set_header X-Forwarded-Host $server_name;

           #timeout
           proxy_read_timeout 18000;
           proxy_connect_timeout 18000;
           proxy_send_timeout 18000;
           send_timeout 18000;
           #try_files $uri @proxy_to_app;
        }

location @proxy_to_app {

           #proxy_pass http://channels-backend;
           proxy_pass http://0.0.0.0:8000;
           proxy_http_version 1.1;
           proxy_set_header Upgrade $http_upgrade;
           proxy_set_header Connection "upgrade";

           #proxy_redirect off;
           proxy_set_header Host $host;
           #proxy_set_header X-Real-IP $remote_addr;
  #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           #proxy_set_header X-Forwarded-Host $server_name;
    }
Enter fullscreen mode Exit fullscreen mode
Collapse
 
lautaronavarro profile image
Lautaro Navarro

Hi Jayden!
First of all I'd like to thank you for this amazing post!
I've been following this post step by step and I'm getting an error when I'm trying to start up de Uvicorn server, which I guess it's related to a breaking change on a dependency.
The error is the following
"module 'websockets' has no attribute 'WebSocketServerProtocol'"
Do you know which is the path to continue?

Collapse
 
lautaronavarro profile image
Lautaro Navarro

I realized that running it from the same directory that the asgi.py file it works, so it looks like I'm doing something wrong with the path :/
Running "uvicorn asgi:application" from the asgi file directory works
Running "uvicorn websockets.asgi:application" from the project's directory does not work (my project is called websockets)

Collapse
 
lautaronavarro profile image
Lautaro Navarro

Well I was able to find the problem, your project must not be called websockets.

Collapse
 
rehmatworks profile image
Rehmat Alam

Thank you so much for sharing this great piece of knowledge. I've been struggling with Websockets and now I feel that I've found a path. And I'm really glad to see this path through Django that I love a lot.

Collapse
 
valentinogagliardi profile image
Valentino Gagliardi • Edited

Thanks for this writeup Jayden. However, I'm wondering if this the right approach, and how maintainable is it. I feel I'd wait for things to settle a bit instead of reinventing the wheel. See github.com/django/deps/blob/master...

Collapse
 
curt114 profile image
curt114

This is a fantastic article. Thank you. How would you use a django database call with this? For example, User.objects.get( pk=1 )?

Collapse
 
pystar profile image
Pystar

This tutorial doesnt work for me. I am getting this traceback:

"TypeError: asgi_send() missing 1 required positional argument: 'message'"

Collapse
 
rohitba12937568 profile image
Rohit Bansal

Hi Jayden!
How can we use same websocket for multiple clients so that multiple users could chat to each other?