0

Thank you all for reading my first post. Using Django 2.02, Django-channels 2.02.

I wish to store informations that get send from the frontend to the backend into Django session store. My problem is that the Django-channels session scope only seems to store information as long as the WebSocket is open, but I need it store it like a Django http-session.

First javascript from frontend index.html.

<script>
const conn = new WebSocket('ws://localhost:8000/');

var msg = {
    type: "message",
    message: "Trying to find a solution",
    date: Date.now(),
};

msg = JSON.stringify(msg);
conn.onopen = () => conn.send(msg);
</script> 

Consumers.py

from channels.generic.websocket import JsonWebsocketConsumer
from importlib import import_module
from django.conf import settings
SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
#Have tried SessionStore to store but will also not work

class ConnectConsumer(JsonWebsocketConsumer):
    def connect(self):
        self.accept()

    def receive(self, text_data=None):
        text = self.decode_json(text_data) #decode incoming JSON
        text_message = text.get('message') 

        print(self.scope["session"]["message"]) #prints "None"
        self.scope["session"]["message"] = text_message
        self.scope['session'].save()
        print(self.scope["session"]["message"]) #prints "Trying to find a solution"

    def disconnect(self, message):
        pass

Routing.py

from django.urls import path
from channels.http import AsgiHandler
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from consumers import ConnectConsumer

application = ProtocolTypeRouter({
    "websocket": AuthMiddlewareStack(
        URLRouter([
            path("/", ConnectConsumer),
        ]),
    )
})

Views.py

from django.shortcuts import render

def index(request):
    print(request.session.keys()) #returns Empty dict([])
    return render(
        request,
        'index.html',
    )

Please tell me if this question is to broad or I am missing relevant information.

Espen Finnesand
  • 475
  • 7
  • 22

2 Answers2

0

Try to change your views.py code to

from django.shortcuts import render

def index(request):
    if not 'message' in request.session.keys():
        request.session['message'] = ''
        print("'message' key created in HTTP session")    
    print(request.session['message']) # it should print "" on the first run
                                      # and "Trying to find a solution" after that
    return render(
        request,
        'index.html',
    )

I'm not quite sure about what causes this issue, but I guess that it is related with the way that the SessionMiddleware works. It seems that the SessionStore.save() method does not save new session keys when called inside the consumers.py. That's why I preallocate the 'message' key in the views.py.


Edit 1 - my consumers.py

from channels.generic.websocket import JsonWebsocketConsumer
#from importlib import import_module
from django.conf import settings
#SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
#Have tried SessionStore to store but will also not work

class ConnectConsumer(JsonWebsocketConsumer):
    def connect(self):
        self.accept()

    def receive(self, text_data=None):
        text = self.decode_json(text_data) #decode incoming JSON
        text_message = text.get('message') 

        print(self.scope["session"]["message"]) 
        self.scope["session"]["message"] = text_message
        self.scope['session'].save()
        print(self.scope["session"]["message"]) #prints "Trying to find a solution"

    def disconnect(self, message):
        pass
bjbschmitt
  • 124
  • 8
  • Thank you for answer bjbschmitt. I tried this but views.py and consumers.py(SessionStore) store information in different session_keys. Can you please post an example of how your consumers.py looks? – Espen Finnesand Mar 01 '18 at 16:19
  • I have used the same `consumers.py` as you. But I'll add it to my answer anyway. Btw, could you please show me your `settings.py` file? Maybe it is something related with your sessions settings. – bjbschmitt Mar 01 '18 at 20:19
  • It now works PERFECTLY! I am sorry, it was my mistake. I tried different solutions, so when I was trying this one, I mixed it up with another solution. I am greatfull. – Espen Finnesand Mar 02 '18 at 20:48
0

I know this thread is a little bit old, but I lost a total day of figuring out why cookies are not being send over the websocket connection and therefore I could not access the correct session in the consumer. Turns out I just had to replace

new WebSocket('ws://localhost:8000/');

with

new WebSocket('ws://127.0.0.1:8000/');

Other than that, it really is important to save the session or the new session key first outside of the consumer (e.g. in a View) like shown in @bjbschmitt answer.

I hope this will save someone a lot of time.

julian
  • 96
  • 3